在单词边界\ b的末尾匹配星号*

时间:2019-10-12 17:36:56

标签: regex profanity

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

使用一个字符串元组,构建一个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 个答案:

答案 0 :(得分:5)

*不是文字字符,因此也不是麻将,如果后面紧跟\b非文字字符

假设初始单词边界很好,但是您想匹配sh*t不匹配 sh*t*,或者匹配f***!不匹配 f***a如何使用负数lookahead模拟自己的单词边界。

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

See this demo at regex101

如果需要,可以用负向后的(?<![\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

示例:

https://regexr.com/4nqie