如何在正则表达式中匹配“在此字符序列之前的任何内容”?

取这个正则表达式:/^[^abc]/。这将匹配字符串开头的任何单个字符,除了一个bc

如果您在它之后添加*-/^[^abc]*/-正则表达式将继续向结果添加每个后续字符,直到它遇到abc

例如,对于源字符串"qwerty qwerty whatever abc hello",表达式将匹配到"qwerty qwerty wh"

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

换句话说,我如何将所有内容匹配到(但不包括)精确序列"abc"

1114589 次浏览

如果你想捕捉到“abc”的所有内容:

/^(.*?)abc/

说明:

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

^匹配行首

.*匹配任何东西,?非贪婪(匹配所需的最小字符数)-[1]

[1]之所以需要这样做,是因为否则,在以下字符串中:

whatever whatever something abc something abc

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

$标志着一个字符串的结束,所以像这样的东西应该工作:[[^abc]*]$,你在abc的任何迭代中寻找没有结束,但它必须在最后

此外,如果您使用的是带有regex的脚本语言(如PHP或JavaScript),它们有一个搜索功能,当它第一次遇到模式时就会停止(您可以指定从左开始或从右开始,或者使用php,您可以执行内爆来镜像字符串)。

我相信您需要子表达式。您可以对子表达式使用普通的()括号。

这部分来自grep手册:

返回引用和子表达式

反向引用\n,其中n是个位数,匹配子字符串之前由第n个带括号的子表达式匹配正则表达式。

^[^(abc)]这样做应该会有效果。

您没有指定您正在使用哪种风格的正则表达式,但这将在任何可以被认为是“完整”的最流行的工作。

/.+?(?=abc)/

它是如何运作的

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

使用.+?时,不要一次匹配所有内容并返回其他条件(如果有),引擎将通过以下方式匹配下一个字符步骤直到正则表达式的后续部分匹配(如果有的话)。这是不贪婪,意思是匹配尽可能少满足

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

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

因此,在其他方面,regex/.+?(?=abc)/意味着:

尽可能少地匹配任何字符,直到找到“abc”。不包括“abc”。

你需要看看断言,比如.+? (?=abc)

见:前视和后视零长度断言

请注意,[abc]abc不同。括号内的字符不是字符串-每个字符只是可能性之一。在括号外,它成为字符串。

正如jared ng和@Issun所指出的,解决这种正则表达式的关键是“将所有内容匹配到某个单词或子字符串”或“匹配某个单词或子字符串之后的所有内容”,称为“环顾”零长度断言。

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

一图胜千言,详解见截图。

Regex101截图

试试这个:

.+?efg

查询:

select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

输出:

hijklmn

对于Java的正则表达式,我相信在大多数正则表达式引擎中,如果你想包含最后一部分,这将起作用:

.+?(abc)

例如,在这一行中:

I have this very nice senabctence

选择所有字符,直到“abc”,并包括abc。

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

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

这将对regex有意义。

确切的单词可以从以下regex命令中获得:

("(.*?)")/g

在这里,我们可以得到属于双引号内的确切单词全局。

例如,如果我们的搜索文本是

这是"双引号"单词的例子

然后我们将从这句话中得到“双重引用”。

所以我不得不即兴发挥……一段时间后,我设法达到了我需要的正则表达式:

在此输入图片描述

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

复制粘贴的文本版本(更改文本的'grp-bps'):

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

在寻找帮助解决我的问题后,我结束了这个堆栈溢出问题,但我没有找到任何解决方案:(

在Python中:

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

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

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

解决方案

/[\s\S]*?(?=abc)/

这将匹配

直到(但不包括)精确序列"abc"的所有内容

正如OP所要求的,即使源字符串包含换行符即使序列以#0开头。但是,如果源字符串可能包含换行符,请务必包含多行标志m

它是如何运作的

\s表示任何空白字符(例如空格、制表符、换行符)

\S表示任何非空白字符;即与\s相反

一起[\s\S]表示任何字符。这与.几乎相同,只是.不匹配换行符。

*表示前面标记的0+次。如果源字符串以abc开头,我使用它而不是+

(?=被称为积极向前看。它需要与括号中的字符串匹配,但在它之前停止,因此(?=abc)意味着“直到但不包括abc,但abc必须存在于源字符串中”。

[\s\S]*(?=abc)之间的?表示懒惰(又名非贪婪)。即停在第一个abc。如果没有这个,如果abc出现不止一次,它将捕获abc出现的最终之前的每个字符。

我想为正则表达式的不区分大小写版本扩展Sidyll的回答

如果您想不敏感地匹配abc/Abc/ABC… case,我需要这样做,请使用以下正则表达式。

.+?(?=(?i)abc)

说明:

(?i) - This will make the following abc match case insensitively.

对正则表达式的另一种解释与西迪尔指出的相同。

匹配从开始到“ABC之前”或“行结束”,如果没有ABC

(1)如果字符串在任何地方不包含ABC,则匹配整个字符串

(2)不匹配空字符串

(不检查带有换行符的字符串)

^.+?(?=ABC|$)

您的问题没有指定后续字符序列是否是可选的,但所有其他答案都假设始终给出该序列。所以这是一个,如果序列是可选的。

例如,如果将代码匹配到foo # ...foo // ...之类的行注释,则行注释本身可能是可选的,但可能仍然希望匹配前面的代码。

在这种情况下,我将使用^(?:(?!abc).)*(或行注释:^(?:(?!#).)*^(?:(?!\/\/).)*)。

解释:
^标记行的开头。(?:)是一个非捕获组,因为常规组会额外捕获组中最后一个匹配的字母,我们不需要。
在组内,我们使用负前瞻(?!).,因此除了特定序列之外,所有内容都匹配。这与*重复0到无限次。如果您只想匹配非空字符串,请使用+