如何在正则表达式中匹配“直到这个字符序列的任何东西”?

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

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

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

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

...换句话说,我怎样才能匹配到(但不包括)确切序列 "abc" 的所有内容?

回答(10)

3 years ago

你没有指定你正在使用哪种正则表达式,但这适用于任何可以被认为是“完整”的最流行的正则表达式 .

/.+?(?=abc)/

它是如何工作的

.+? 部分是 .+ (一个或多个任何东西)的非贪婪版本 . 当我们使用 .+ 时,引擎基本上会匹配所有内容 . 然后,如果正则表达式中还有其他内容,它将返回尝试匹配以下部分的步骤 . 这是 greedy 行为,意思是 as much as possible to satisfy .

当使用 .+? 时,不是一次匹配all而是返回其他条件(如果有的话),引擎将逐步匹配下一个字符,直到匹配正则表达式的后续部分(如果有的话) . 这是 un-greedy ,意思是匹配 the fewest possible to satisfy .

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

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

接下来我们有一个零宽度断言,环顾四周 . 此分组构造与其内容匹配,但不计为匹配的字符( zero width ) . 它只会在匹配时返回( assertion ) .

因此,在其他方面,正则表达式 /.+?(?=abc)/ 表示:

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

3 years ago

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

/^(.*?)abc/

说明:

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

^ 匹配行的开头

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

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

whatever whatever something abc something abc

默认情况下,正则表达式是贪婪的,这意味着它将尽可能匹配 . 因此 /^.*abc/ 将匹配"whatever whatever something abc something " . 添加非贪心量词 ? 使正则表达式只匹配"whatever whatever something " .

3 years ago

正如@Jared Ng和@Issun指出的那样,解决像"matching everything up to a certain word or substring"或"matching everything after a certain word or substring"这样的RegEx的关键是"lookaround"零长度断言 . Read more about them here.

在您的特定情况下,可以通过积极展望来解决 . 一张图片胜过千言万语 . 请参阅屏幕截图中的详细说明 .

Regex101 Screenshot

3 years ago

你需要的是看看像 .+? (?=abc) 这样的断言 .

见:Lookahead and Lookbehind Zero-Length Assertions

请注意 [abc]abc 不同 . 在括号内,它不是一个字符串 - 每个字符只是其中一种可能性 . 在括号外面它变成了字符串 .

3 years ago

这对正则表达式有意义 .

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

(“( . *?)”)/ g

在这里,我们可以获得属于双引号内的全局字 . 例如,如果我们的搜索文本是,

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

那么我们将从那句话中得到“双引号” .

3 years ago

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

.+?(abc)

例如,在这一行:

I have this very nice senabctence

选择所有字符,直到"abc"并包括abc

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

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

3 years ago

我相信你需要子表达式 . 如果我没记错,你可以使用普通的 () 括号来表示子表达式 .

这部分是从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)] 这样的东西应该可以做到 .

3 years ago

我找到帮助解决我的问题后,在这个stackoverflow问题结束但发现没有解决方案:(

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

enter image description here

如您所见,我需要在“grp-bps”文件夹之前最多一个文件夹,而不包括最后一个短划线 . 并且需要在“grp-bps”文件夹后至少有一个文件夹 .

3 years ago

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

此外,如果您使用带有正则表达式的脚本语言(如php或js),它们会有一个搜索功能,当它第一次遇到模式时会停止(您可以指定从左侧开始或从右侧开始,或者使用php,你可以做一个内爆镜像字符串) .

3 years ago

试试这个

.+?efg

查询:

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

输出:

hijklmn