1

在构建一个轻量级的工具来检测被审查的亵渎行为时,我注意到在单词边界的末尾检测特殊字符是非常困难的。

使用字符串元组,我构建了一个 OR'd 单词边界正则表达式:

import re

PHRASES = (
    'sh\\*t',  # easy
    'sh\\*\\*',  # difficult
    'f\\*\\*k',  # easy
    'f\\*\\*\\*',  # difficult
)

MATCHER = re.compile(
    r"\b(%s)\b" % "|".join(PHRASES), 
    flags=re.IGNORECASE | re.UNICODE)

问题是在*单词边界旁边无法检测到\b

print(MATCHER.search('Well f*** you!'))  # Fail - Does not find f***
print(MATCHER.search('Well f***!'))  # Fail - Does not find f***
print(MATCHER.search('f***'))  # Fail - Does not find f***
print(MATCHER.search('f*** this!'))  # Fail - Does not find f***
print(MATCHER.search('secret code is 123f***'))  # Pass - Should not match
print(MATCHER.search('f**k this!'))  # Pass - Should find 

有什么想法可以方便地进行设置以支持以特殊字符结尾的短语吗?

4

4 回答 4

5

如果后跟\b非单词字符*则不是单词字符,因此没有马赫。

假设初始单词边界很好,但您想要匹配sh*t sh*t*匹配或匹配f***! f***a匹配如何通过使用负前瞻来模拟您自己的单词边界。

\b(...)(?![\w*])

在 regex101 看到这个演示

如果需要,可以将开头的单词边界\b替换为否定的lookbehind:(?<![\w*])

于 2019-10-28T09:48:51.960 回答
1

使用您对短语开头和结尾的了解,并将它们与相应的匹配器一起使用。
这是一个静态版本,但很容易根据开始和结束自动对传入的新短语进行排序。

import re

PHRASES1 = (
    'sh\\*t',  # easy
    'f\\*\\*k',  # easy
)
PHRASES2 = (
    'sh\\*\\*',  # difficult
    'f\\*\\*\\*',  # difficult
)
PHRASES3 = (
    '\\*\\*\\*hole', 
)
PHRASES4 = (
    '\\*\\*\\*sonofa\\*\\*\\*\\*\\*',  # easy
)
MATCHER1 = re.compile(
    r"\b(%s)\b" % "|".join(PHRASES1), 
    flags=re.IGNORECASE | re.UNICODE)
MATCHER2 = re.compile(
    r"\b(%s)[$\s]" % "|".join(PHRASES2), 
    flags=re.IGNORECASE | re.UNICODE)
MATCHER3 = re.compile(
    r"[\s^](%s)\b" % "|".join(PHRASES3), 
    flags=re.IGNORECASE | re.UNICODE)
MATCHER4 = re.compile(
    r"[\s^](%s)[$\s]" % "|".join(PHRASES4), 
    flags=re.IGNORECASE | re.UNICODE)
于 2019-10-12T17:59:02.660 回答
0

可以在每个字符串中嵌入边界要求,例如

'\\bsh\\*t\\b', 
'\\bsh\\*\\*',  
'\\bf\\*\\*k\\b',  
'\\bf\\*\\*\\*', 

然后r"(%s)" % "|".join(PHRASES)

或者,如果正则表达式引擎支持条件,它会像这样完成

'sh\\*t', 
'sh\\*\\*',  
'f\\*\\*k',  
'f\\*\\*\\*', 

然后 r"(?(?=\w)\b)(%s)(?(?<=\w)\b)" % "|".join(PHRASES)

于 2019-10-12T17:54:21.867 回答
0

我不完全理解您的陈述,这*不是可以在单词边界旁边找到的东西。但是,如果我从评论中正确理解了您正在寻找的内容,我认为这会起作用:

\b[\w]\*+[\w]*
  • 字边界
  • 后面跟着一些字母,比如f
  • 后跟一个或多个*
  • 可选择以某个字母结尾,例如k

例子:

https://regexr.com/4nqie

于 2019-10-29T19:46:56.350 回答