正则表达式:直到但不包括

109

对于正则表达式,搜索直至但不包括的语法是什么?类似于:

Haystack:
The quick red fox jumped over the lazy brown dog

Expression:
.*?quick -> and then everything until it hits the letter "z" but do not include z
3个回答

206

表达“搜索到X但不包括X”的明确方式是:

(?:(?!X).)*

其中X可以是任何正则表达式。

然而,在您的情况下,这可能过于复杂 - 在这里最简单的方法是

[^z]*

这将匹配除了 z 以外的任何字符,并因此停在下一个 z 前面。

所以 .*?quick[^z]* 将匹配 The quick fox jumps over the la

然而,一旦你需要查找不止一个简单字母时,(?:(?!X).)* 就会发挥作用,例如

(?:(?!lazy).)* - 匹配任何东西直到单词 lazy 的开头。

这是使用了一个前瞻断言,更具体地说是负向前瞻。

.*?quick(?:(?!lazy).)* 将匹配 The quick fox jumps over the

解释:

(?:        # Match the following but do not capture it:
 (?!lazy)  # (first assert that it's not possible to match "lazy" here
 .         # then match any character
)*         # end of group, zero or more repetitions.

此外,在搜索关键字时,您可能希望用单词边界锚定符将它们括起来:\bfox\b只会匹配完整的单词fox,而不是在foxy中的fox。
请注意:
如果要匹配的文本还可以包含换行符,则需要设置正则表达式引擎的"点匹配所有"选项。通常,您可以通过在正则表达式前面添加(?s)来实现这一点,但并不适用于所有正则表达式引擎(特别是JavaScript)。
替代方案:
在许多情况下,您还可以使用更简单、更易读的解决方案,该解决方案使用惰性量词。通过在*量词后面添加一个?,它将尝试从当前位置尽可能少地匹配字符:
.*?(?=(?:X)|$)

将匹配任意数量的字符,停在X(可以是任何正则表达式)或字符串结尾之前(如果X不匹配)。您可能还需要设置“点匹配所有”选项才能使其工作。(注意:我添加了一个非捕获组来可靠地将X与交替分隔开)


+1 很好的答案,不幸的是在使用 grep 时不起作用,但是这个答案可以。 - Alexandre Lavoie
1
真的不知道,我不是正则表达式专家也不是grep。我使用grep来过滤mysql bin转换为sql的请求,只保留一个数据库。这是命令:grep -Po "(?s)use database_to_keep(.*?)(?=^use)" mysql-bin.000045.sql > filtered.sql - Alexandre Lavoie
看起来像是一个bash冲突,因为当我按上箭头键时,最后一个命令不是我使用的那个:grep -Po"(?s)use database_to_keep(.*?)(?:(?!^use).)*"mysql-bin.000045.sql>filtered.sql - Alexandre Lavoie
上下文是我想从(行首)use database_name(多行)(行首)use another_database_name 进行过滤。但是,你对于(.*?)这部分是正确的。 - Alexandre Lavoie
1
好的编辑,@Tim,只需添加 $ 替代方案:将 .*?(?=X) 替换为 .*?(?=X|$) - Wiktor Stribiżew
显示剩余3条评论

20
一个向前查找正则表达式语法 可以帮助你实现目标。因此,你的示例的正则表达式为:
.*?quick.*?(?=z)

重要的是注意在 (?=z) 前面的 .*? 懒惰匹配:该表达式匹配子字符串直到第一次出现 z 字母。

这里是 C# 代码示例:

const string text = "The quick red fox jumped over the lazy brown dogz";

string lazy = new Regex(".*?quick.*?(?=z)").Match(text).Value;
Console.WriteLine(lazy); // The quick red fox jumped over the la

string greedy = new Regex(".*?quick.*(?=z)").Match(text).Value;
Console.WriteLine(greedy); // The quick red fox jumped over the lazy brown dog

0

试试这个

(.*?quick.*?)z

3
这包括匹配中的"z",这正是提问者想要避免的。也许这个正则表达式旨在成为'|'中的一个项,并且该备选正则表达式用于执行多个匹配。如果"z"是由备选项中的另一个项匹配的字符串的开头,那么这个匹配将被放弃,因为"z"已经被当前匹配使用了。 - Szczepan Hołyszewski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接