如何在正则表达式中匹配“直到该字符序列的所有内容”?


514

采取以下正则表达式:/^[^abc]/。这将匹配字符串开头的任何单个字符,但a,b或c除外。

如果添加*后- /^[^abc]*/-正则表达式将会继续后面的每个字符添加到结果,直到遇到的任何a b c

例如,使用源字符串"qwerty qwerty whatever abc hello",表达式将匹配"qwerty qwerty wh"

但是如果我希望匹配的字符串是 "qwerty qwerty whatever "

...换句话说,我该如何匹配所有(但不包括)确切顺序的内容 "abc"


你是什么意思match but not including
Toto

5
我的意思是我想匹配"qwerty qwerty whatever "-不包括“ abc”。换句话说,我希望结果为"qwerty qwerty whatever abc"
2011年

2
在javascript中,您可以do string.split('abc')[0]。当然不是这个问题的官方答案,但是我发现它比正则表达式更直接。
威廉·贾德

Answers:


1020

您没有指定要使用哪种正则表达式,但这可以在任何可以被视为“完整”的最流行的正则表达式中使用。

/.+?(?=abc)/

怎么运行的

.+? 部分是.+ (任何一项或多项)的非贪婪版本 。当我们使用时.+,引擎将基本匹配所有内容。然后,如果正则表达式中还有其他内容,它将分步返回以尝试匹配以下部分。这是 贪婪的行为,意味着尽可能满足

当使用时 .+?,引擎将一次匹配所有下一个字符,直到匹配正则表达式的后续部分(再次匹配),而不是一次匹配所有条件并返回其他条件(如果有的话)。这是不贪心,意味匹配 最少的满足

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

之后,我们有了 一个 零宽度的断言环顾四周。此分组的构造与其内容匹配,但不算作匹配的字符(零宽度)。它仅在是否匹配(断言)时返回。(?={contents})

因此,换句话说,正则表达式/.+?(?=abc)/表示:

尽可能少地匹配任何字符,直到找到“ abc”为止,而不计算“ abc”。


12
如果应该捕获换行符,这可能不适用于换行符。
einord '16

3
.+?和之间有什么区别.*
robbie

4
@ robbie0630 +表示1或更大,其中*0或更大。包含/排除?将使它变得贪婪或不贪婪。
jinglesthula

2
@ testerjoe2 /.+?(?=abc|xyz)/
JohnWrensby

4
我注意到,如果您要查找的模式不存在,这将无法选择任何内容,相反,如果您可以使用^(?:(?!abc)(?!def).)*链式排除不需要的模式,即使该模式不存在,它仍会根据需要捕获所有内容
Karan Shishoo

121

如果您希望捕获所有不超过“ abc”的内容:

/^(.*?)abc/

说明:

( )使用捕获的括号内的访问的表达$1$2等等。

^ 匹配行首

.*?非贪婪地匹配任何内容(匹配所需的最少字符数)-[1]

[1]之所以需要这样做,是因为以下原因:

whatever whatever something abc something abc

默认情况下,正则表达式是greedy,这意味着它将尽可能匹配。因此/^.*abc/将匹配“无论什么东西abc东西”。添加非贪婪的量词?会使正则表达式仅匹配“无论任何事物”。


4
谢谢,但是您的比赛中确实包含了abc。换句话说,结果匹配是“无论什么东西abc”。
2011年

1
您能解释一下您最终想要做什么吗?如果您的情况是:(A)您想要使所有内容都达到“ abc”-只需在要捕获的内容周围使用括号即可。(B)您想将字符串最多匹配到“ abc”-无论如何都必须检查abc,因此无论如何它都必须是正则表达式的一部分。您还能如何检查它在那里?
贾里德伍

sed似乎不支持非贪婪匹配,也不支持环视((?=...))。我还可以做些什么?例如命令:echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"回报two,three, FOUR FIVE,但我希望two,three...
CodeManX

1
@CoDEmanX您可能应该将其发布为您自己的单独问题而不是评论,尤其是因为它特别与sed有关。话虽这么说,以解决您的问题:您可能想看看这个问题的答案。还要注意,在您的示例中,一个非贪婪的解释器将返回just two,而不是two,three
伍瑞杰(Jared Ng)

3
这是怎么EVERY正则表达式的答案应该看-例如与各地的解释 ...
jave.web

54

正如@Jared Ng和@Issun指出的那样,解决此类RegEx的关键,例如“将所有内容匹配到一个特定的单词或子字符串”或“将所有内容匹配到某个特定的单词或子字符串”,称为“环顾四周”零长度断言。在这里阅读有关它们的更多信息。

在您的特定情况下,可以通过积极的展望来解决: .+?(?=abc)

一张图片胜过千言万语。请参阅屏幕截图中的详细说明。

Regex101截图


23
.+?(?=abc)复制可粘贴的正则表达式值得更多。
汤姆

那排除前导空格呢?
罗伊


7

对于Java中的regex,我也相信大多数regex引擎,如果要包括最后一部分,则可以使用:

.+?(abc)

例如,在这一行:

I have this very nice senabctence

选择所有字符,直到“ abc”为止,还包括abc

使用我们的正则表达式,结果将是: I have this very nice senabc

测试一下:https : //regex101.com/r/mX51ru/1


4

在寻求帮助来解决我的问题之后,我以这个stackoverflow问题结束了,但没有找到解决方案的方法:(

所以我不得不即兴创作...一段时间后,我设法达到所需的正则表达式:

在此处输入图片说明

如您所见,在“ grp-bps”文件夹之前,我最多需要一个文件夹,但不包括最后一个破折号。并且要求在“ grp-bps”文件夹之后至少有一个文件夹。

编辑

复制粘贴的文本版本(将文本更改为“ grp-bps”):

.*\/grp-bps\/[^\/]+

6
没有文字版本?🙄–
kiradotee

2

这将使正则表达式有意义。

  1. 确切的词可以从以下regex命令获得:

(“(。*?)“)/G

在这里,我们可以全局获取确切的单词,该单词属于双引号。例如,如果我们的搜索文字是

这是“双引号”单词的示例

那么我们将从该句子中获得“双引号”。


欢迎使用StackOverflow,并感谢您的帮助。但是,我发现很难看到这如何帮助问题中所述的目标。你能详细说明吗?您可以将其应用于给定的示例吗?您似乎专注于处理",对我而言,这似乎与问题无关。
Yunnosch

1
嗨,我已经解释了如何在特殊字符之间得到单词或句子。在这里,我们的问题也是“直到特殊字符序列为止的所有内容”。所以我尝试用双引号并在这里解释。谢谢。
Ponmurugan Mohanraj

2

在python上:

.+?(?=abc) 适用于单行情况。

[^]+?(?=abc)不起作用,因为python无法将[^]识别为有效的正则表达式。要使多行匹配有效,您需要使用re.DOTALL选项,例如:

re.findall('.+?(?=abc)', data, re.DOTALL)

0

我相信您需要子表达式。如果我没记错的话,可以在()子表达式中使用普通括号。

这部分来自grep手册:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

做类似^[^(abc)]应该做的事情。


抱歉,这不起作用。将abc放在括号中似乎没有任何区别。它们仍被视为“ a OR b OR c”。
2011年

-1

$标记的字符串的结束,所以这样的事情应该工作:[[^abc]*]$你在哪里寻找什么在任何迭代不是终止abc,但它必须是在结束

另外,如果您将脚本语言与regex结合使用(例如php或js),则它们具有一个搜索功能,该功能会在遇到模式时停止(您可以指定从左开始或从右开始,或者从php开始,您可以进行内爆以镜像字符串)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.