在构建一个轻量级的工具来检测被检查的亵渎用法时,我注意到在单词边界末尾检测特殊字符非常困难。
使用一个字符串元组,构建一个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
有什么方便的设置方法来支持以特殊字符结尾的短语吗?
答案 0 :(得分:5)
*
不是文字字符,因此也不是麻将,如果后面紧跟\b和非文字字符。
假设初始单词边界很好,但是您想匹配sh*t
但不匹配 sh*t*
,或者匹配f***!
但不匹配 f***a
如何使用负数lookahead模拟自己的单词边界。
\b(...)(?![\w*])
如果需要,可以用负向后的(?<![\w*])
\b
。
答案 1 :(得分:1)
可以在每个字符串中嵌入边界要求,例如
'\\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)
答案 2 :(得分: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)
答案 3 :(得分:0)
我不完全理解您所说的*
不是在单词边界旁边的说法。但是,如果我从评论中正确理解了您要寻找的内容,那么我认为这会起作用:
\b[\w]\*+[\w]*
f
*
k
示例: