Python中的正则表达式负向先行行为
我有一个正则表达式,它应该能找到一行中的最多10个单词。也就是说,它应该包括换行符前面的那个单词,但不包括换行符后面的单词。我在使用一个负向前瞻来处理换行符"\n"。
a = re.compile(r"((\w)+[\s /]){0,10}(?<!\n)")
r = a.search("THe car is parked in the garage\nBut the sun is shining hot.")
当我执行这个正则表达式并调用方法r.group()时,我得到的是整个句子,但最后一个单词后面有个句号。我原本只想要换行符前的完整字符串,也就是“车停在车库里\n”。我在使用负向前瞻时到底哪里出错了呢……?
4 个回答
如果我理解得没错,你想要读取最多10个单词,或者遇到第一个换行符,先到者为准:
((?:(?<!\n)\w+\b[\s.]*){0,10})
这里使用了一个负向前瞻,但它是在单词匹配之前,所以它会阻止获取换行符后面的任何单词。
这个方法可能需要根据不完美的输入进行一些调整,但这算是一个开始。
在这个任务中,有一个锚点 $
用来找到字符串的结尾,配合修饰符 re.MULTILINE
/re.M
,它可以找到行的结尾。所以你最终会得到类似这样的东西:
(\b\w+\b[.\s /]{0,2}){0,10}$
你可以在 这里查看 Regexr
\b
是一个单词边界。我在我的例子中加入了 [.\s /]{0,2}
来匹配一个点后面跟着一个空格。如果你不想要点的话,你需要把这一部分至少设为可选,比如 [\s /]?
,否则它会在最后一个单词缺失,然后 \s
就会匹配到 \n
。
更新/想法 2
好的,也许我在第一个解决方案中误解了你的问题。
如果你只是想避免匹配换行符并继续到第二行,那就不要允许换行符。问题在于,换行符被你字符类中的 \s
匹配了。\s
是一个空白字符的类,它也包括换行符 \r
和 \n
。
你已经在类中有一个空格了,所以如果你想允许制表符,可以把 \s
替换成 \t
,这样就可以不使用回顾了。当然,要把字符类设为可选,否则最后一个单词也会不匹配。
((\w)+[\t /]?){0,10}
你可以在 这里查看 Regexr
我不太明白你为什么要用负向前瞻。你提到你想在换行符之前最多有10个单词。下面的正则表达式应该可以满足这个需求。它使用了正向前瞻,确保在这些单词后面确实有一个换行符。而且在查找单词时,建议使用 `b\w+\b`,而不是你之前用的那种方式。
/(\b\w+\b)*(?=.*\\n)/
Python :
result = re.findall(r"(\b\w+\b)*(?=.*\\n)", subject)
解释:
# (\b\w+\b)*(?=.*\\n)
#
# Match the regular expression below and capture its match into backreference number 1 «(\b\w+\b)*»
# Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
# Note: You repeated the capturing group itself. The group will capture only the last iteration. Put a capturing group around the repeated group to capture all iterations. «*»
# Assert position at a word boundary «\b»
# Match a single character that is a “word character” (letters, digits, etc.) «\w+»
# Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
# Assert position at a word boundary «\b»
# Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=.*\\n)»
# Match any single character that is not a line break character «.*»
# Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
# Match the character “\” literally «\\»
# Match the character “n” literally «n»
你可能还需要考虑到你的字符串中可能没有换行符(\n)。