我有以下情况,匹配似乎无法正常工作:
import re
test_case1 = u"I will meet you at 2 pm"
test_case2 = u"I will meet you at 2 p.m."
test_case3 = u"I will meet you at 2 p.m. "
test_case4 = u"I will meet you at 2 p.m. pm "
list_of_words = ['p.m.', 'pm'] # list of words that can be enlarged
# join all words into an or expression and escape all punctuation
joined_words = '|'.join([re.escape(x) for x in list_of_words])
# create a regex that will match a word from the list of words only if it is
# at the start/end of the sentence or it is between two word boundaries
match_regex = r'(^|\b)('+joined_words+r')(\b|$)'
comp_regex = re.compile(match_regex, re.IGNORECASE) # compile the final regex
print comp_regex.findall(test_case1), len(comp_regex.findall(test_case1))
print comp_regex.findall(test_case2), len(comp_regex.findall(test_case2))
print comp_regex.findall(test_case3), len(comp_regex.findall(test_case3))
print comp_regex.findall(test_case4), len(comp_regex.findall(test_case4))
我得到了 4 个测试用例的以下结果:
[(u'', u'pm', u'')] 1
[(u'', u'p.m.', u'')] 1
[] 0
[(u'', u'pm', u'')] 1
第一种和第二种情况似乎工作正常,第三种不匹配“p.m.”如果它后面有空格,即使我在正则表达式中使用了“\b”字边界。
第 4 种情况似乎与“p.m.”不匹配。完全匹配,并且只匹配“pm”。
我似乎无法理解问题出在哪里,感谢任何帮助。
请您参考如下方法:
Python docs关于 \b 的状态如下:
Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of alphanumeric or underscore characters, so the end of a word is indicated by whitespace or a non-alphanumeric, non-underscore character. Note that formally, \b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string, so the precise set of characters deemed to be alphanumeric depends on the values of the UNICODE and LOCALE flags. For example, r'\bfoo\b' matches 'foo', 'foo.', '(foo)', 'bar foo baz' but not 'foobar' or 'foo3'. Inside a character range, \b represents the backspace character, for compatibility with Python’s string literals.
根据该定义,. 不能标记单词的结尾,因此 \b 在 p.m. 之后不匹配。如果您对匹配项进行以下更改,您将获得预期的行为:
match_regex = r'(^|\b)('+joined_words+r')(\s|$)'
