Python 正则表达式中的可选点
假设我想将Python 正则表达式中的可选点,python,regex,python-2.7,Python,Regex,Python 2.7,假设我想将Mr.和Mr的所有匹配项替换为Mister 我正在使用以下正则表达式:\bMr(\)?\b来匹配Mr.或只匹配Mr。然后,我用这个来做替换 让我困惑的是,它正在用先生取代先生。。为什么要把点保留在最后?看起来它与Mr\.案例不匹配,而只是Mr import re s="a rMr. Nobody Mr. Nobody is Mr Nobody and Mra Nobody." re.sub(r"\bMr(\.)?\b","Mister", s) 返回: 'a rMr. Nobody
Mr.
和Mr
的所有匹配项替换为Mister
我正在使用以下正则表达式:\bMr(\)?\b
来匹配Mr.
或只匹配Mr
。然后,我用这个来做替换
让我困惑的是,它正在用先生取代先生。
。为什么要把点
保留在最后?看起来它与Mr\.
案例不匹配,而只是Mr
import re
s="a rMr. Nobody Mr. Nobody is Mr Nobody and Mra Nobody."
re.sub(r"\bMr(\.)?\b","Mister", s)
返回:
'a rMr. Nobody Mister. Nobody is Mister Nobody and Mra Nobody.'
我还尝试了以下方法,但也没有成功:
re.sub(r"\b(Mr\.|Mr)\b","Mister", s)
我期望的输出是:
'a rMr. Nobody Mister Nobody is Mister Nobody and Mra Nobody.'
^ ^
no dot this should be kept as it is
尝试此操作。您需要在
之后删除\b
输出:a rMr。没有人先生没有人是先生没有人和Mra没有人。
\bMr(\)?\b
不起作用的原因是
和空格之间没有单词边界
有三种不同的位置可以作为单词边界:
- 在字符串的第一个字符之前,如果第一个字符是单词字符
- 如果最后一个字符是单词字符,则在字符串中最后一个字符之后
- 在字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符
我认为您希望捕获'Mr'
,然后是一个'.
或一个单词边界:
使用中:
>>> import re
>>> re.sub(r"\bMr(?:\.|\b)", "Mister", "a rMr. Nobody Mr. Nobody is Mr Nobody and Mra Nobody.")
'a rMr. Nobody Mister Nobody is Mister Nobody and Mra Nobody.'
@jonsharpe的答案是可行的,但这一个更简单:\bMr(\.\124;\ b)
我认为在最初的帖子中,\b
是一些混乱的原因
发件人:
\b在不使用任何字符的情况下,在a
与\w匹配的字符和与\w不匹配的字符
订单)
及
\w匹配任何字母、数字或下划线
OP希望\b
与点和它后面的空格之间的边界相匹配。但它没有,因为点与\w
不匹配。相反,\b
匹配了“Mr”文本和点之间的边界。这导致圆点没有被捕获,这就是OP所问的问题。这可以在这里看到:
re.sub(r'\bMr[\s\.]', 'Mister ', s)
如果这是Code Golf,我会赢吗?您正在对可选的“.”字符进行分组。您还可以使用变通方法@hwnd,这是一种很好的方法!我喜欢,谢谢。@fedorqui你想在foo:Mr:bar
中匹配Mr
吗?@AvinashRaj:
不可能出现在我的字符串中。唯一可能的情况是mrnobody
,也应该扩展到Mister
。因此,我们的想法是所有Mr
或Mr.
应该扩展到Mister
,除非后面出现字母数字字符。很抱歉,我的问题不够清楚:Mra
必须保持原样,我不希望它被替换为Mistera
。也就是说,我想要Mr.
或Mr
+word boundary.OP不想在Mr.hghgh
中匹配Mr.
,这是一个很好的答案,非常感谢您对我做错了什么、您如何才能正确地做以及为什么这样做的非常深刻的解释。我选择@jornsharpe的答案作为被接受的答案,因为它更直截了当,但肯定会提高投票率。(?:…)
是为了避免不必要的捕获。但它给出了所需的输出。当然,它确实如此,但这个答案有什么改进?另一个答案显式地使组不被捕获,以稍微减少开销。这个答案中有更少的符号供读者解析。来自Python的禅宗:“可读性很重要。”很好!哪些边缘案例阻止了?:
?对我来说,\bMr(\.\124;\ b)
工作得很好。@fedorqui在Mr
之后有什么需要捕获点或单词边界?@fedorqui(\.\124;\ b)
也捕获Mr后面的任何内容,因此你可以,例如,在你重新定义句子后重新使用它<代码>?:
使它不会发生。它几乎不会对性能和可读性产生任何影响,但如果您将一个组重复未知的次数,然后需要捕获该重复组后面的一个组,那么它将非常有帮助。使重复组不被捕获意味着您提前知道被捕获组的索引是什么,而不必首先计算它。@NateKerkhofs我想说,它对可读性有很大的影响,特别是在这种情况下,如果它毫无意义的话。编写\bMr\b\不是更简单吗?
?有趣!请注意,虽然以Mr开头的字符串不会被当前解决方案替换。这就是单词边界的原因。很好!我是按字面上的例子去做的。我删除了解决方案,留下了问题的解释。@fedorqui-谢谢-这当然是我的本意。␣没有人告诉先生␣␣没有人也就是说,它增加了一个额外的空间。请参见regex101.com/r/dE1yF6/1这项工作,但它会将“Mr”之后的多个空格替换为一个空格。请参阅以避免此问题,您可以使用re.sub(r'\b(Mr(\)?(\s+))、r'Mister\3',s)
。看见
>>> import re
>>> re.sub(r"\bMr(?:\.|\b)", "Mister", "a rMr. Nobody Mr. Nobody is Mr Nobody and Mra Nobody.")
'a rMr. Nobody Mister Nobody is Mister Nobody and Mra Nobody.'
>>> s="a rMr. Nobody Mr. Nobody is Mr Nobody and Mra Nobody."
>>> re.sub(r'\b(Mr[\.\s]\s*)',r'Mister ',s)
'a rMr. Nobody Mister Nobody is Mister Nobody and Mra Nobody.'
re.sub(r'\bMr[\s\.]', 'Mister ', s)