我有一个来自earlier question的以下Python正则表达式模式:
regex_pat = re.compile('''
(
[a-zA-Z\*]*
\*
[a-zA-Z\*]*
)+
''', re.VERBOSE)
现在,如果任何数字与“单词”混合,我希望匹配失败,尤其是在开头或结尾。
text = '''
(A) Match these:
*** star* st**r
(B) Not these:
800*m *4,500
(C) And not these:
800**m **4,000
'''
通过在不同的地方尝试一对负前瞻和负面的后视,我可以摆脱(B)匹配,但不是(C)匹配。例如:
regex_pat = re.compile('''
(
[a-zA-Z\*]*
(?<!\d)
\*
(?!\d)
[a-zA-Z\*]*
)+
''', re.VERBOSE)
regex_pat.findall(text)
# ['***', 'star*', 'st*r', '**m', '**'] The last two matches are no good.
显然,当正则表达式出现负面预测时,它需要退一步才能看出它是否可以获得匹配。我怎么能让负面看起来更贪婪或更具破坏性呢?
你可以用
(?<!\S)(?!\*+\d)[a-zA-Z]*\*[a-zA-Z*]*
细节
(?<!\S)
- 字符串或空格的开头(?!\*+\d)
- 如果在一个或多个星号之后有一个数字,则失败[a-zA-Z]*
- 0+个字母\*
- 星号[a-zA-Z*]*
- 0+字母或星号。重点是在字符串的开头或空格后开始匹配,检查一个或多个星号后是否没有数字,然后匹配您需要的模式。
import re
text = '''
(A) Match these:
*** star* st**r
(B) Not these:
800*m *4,500
(C) And not these:
800**m **4,000
'''
print(re.findall(r'(?<!\S)(?!\*+\d)[a-zA-Z]*\*[a-zA-Z*]*', text))
# => ['***', 'star*', 'st**r']
这个对我自己的问题的回答受到了WiktorStribiżew的评论的启发。它似乎工作。我在这里张贴它,以便更敏锐的眼睛可以告诉我任何缺陷。
regex_pat = re.compile('''
(?<!\S)
[a-zA-Z*]*
\*
[a-zA-Z*]*
(?!\S)
''', re.VERBOSE)
我理解的逻辑是,前瞻和后视强制任何匹配成为一个完整的“单词”,从那里,你将不必再担心匹配中的数字,因为它们不是定义的角色的一部分无论如何都要匹配。