这是我尝试用正则表达式做的事情,我无法弄清楚如何做。我有一个大文件,以及在整个文件中多次出现的字符串abc
,123
和xyz
。
我想要一个正则表达式来匹配以abc
开头的大文件的子字符串,在中间某处包含123
,以xyz
结尾,并且除了开头和结尾之外,子字符串中没有abc
或xyz
的其他实例。
这是否可以使用正则表达式?
答案 0 :(得分:29)
您需要 tempered greedy token :
abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz
请参阅regex demo
要确保它跨行匹配,请在编译正则表达式时使用re.DOTALL
标志。
请注意,为了在如此繁重的模式下获得更好的性能,您应该考虑展开它。它可以用否定的字符类和负向前瞻来完成。
模式详情:
abc
- 匹配abc
(?:(?!abc|xyz|123).)*
- 匹配任何不是abc
,xyz
或123
字符序列起点的字符123
- 文字字符串123
(?:(?!abc|xyz).)*
- 任何不是abc
或xyz
字符序列起点的字符xyz
- 尾随子字符串xyz
请参阅下图(如果使用re.S
,.
将表示AnyChar
):
请参阅Python demo:
import re
p = re.compile(r'abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz', re.DOTALL)
s = "abc 123 xyz\nabc abc 123 xyz\nabc text 123 xyz\nabc text xyz xyz"
print(p.findall(s))
// => ['abc 123 xyz', 'abc 123 xyz', 'abc text 123 xyz']
答案 1 :(得分:3)
使用PCRE的解决方案是:
这使用m
标志。如果您只想从一行的开头和结尾检查,请分别在开头和结尾添加^
和$
abc(?!.*(abc|xyz).*123).*123(?!.*(abc|xyz).*xyz).*xyz
答案 2 :(得分:2)
comment hvd非常合适,这只是一个例子。例如,在SQL中,我认为这样做会更清楚:
where val like 'abc%123%xyz' and
val not like 'abc%abc%' and
val not like '%xyz%xyz'
我认为在其他环境中很容易做到相似的事情。
答案 3 :(得分:1)
您可以使用环视。
/^abc(?!.*abc).*123.*(?<!xyz.*)xyz$/g
(我还没有测试过。)