ChatGPT解决这个技术问题 Extra ChatGPT

如何在正则表达式中匹配“直到此字符序列为止的任何内容”?

采用这个正则表达式:/^[^abc]/。这将匹配字符串开头的任何单个字符,ab 或 *c 除外。

如果您在其后添加 */^[^abc]*/ – 正则表达式将继续将每个后续字符添加到结果中,直到遇到 a b、<强>或 c

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

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

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

match but not including 是什么意思?
我的意思是我想匹配 "qwerty qwerty whatever " - 不包括“abc”。换句话说,我希望结果匹配是 "qwerty qwerty whatever abc"
在 javascript 中,您只需 do string.split('abc')[0]。当然不是这个问题的官方答案,但我发现它比正则表达式更直接。

s
sidyll

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

/.+?(?=abc)/

这个怎么运作

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

使用 .+? 时,引擎将逐步匹配下一个字符,直到匹配正则表达式的后续部分(如果有,再次匹配),而不是一次匹配所有条件并返回其他条件(如果有)。这是un-greedy,意思是匹配尽可能少的满足

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

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

之后我们有 (?={contents}),一个零宽度断言,一个环顾。此分组结构与其内容匹配,但不计为匹配的字符(零宽度)。它仅在匹配与否时才返回(assertion)。

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

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


如果应该捕获换行符,这可能不适用于换行符。
.+?.* 有什么区别?
@robbie0630 + 表示 1 或更多,其中 * 表示 0 或更多。 ? 的包含/排除将使其变得贪婪或非贪婪。
@testerjoe2 /.+?(?=abc|xyz)/
我注意到,如果您要查找的模式不存在,这将无法选择任何内容,相反,如果您使用 ^(?:(?!abc)(?!def).)*,您可以链接以排除您不想要的模式,即使模式确实存在,它仍会根据需要抓取所有内容不存在
J
Jared Ng

如果您要捕获“abc”以下的所有内容:

/^(.*?)abc/

解释:

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

^ 匹配行首

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

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

whatever whatever something abc something abc

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


谢谢,但是您的确实在比赛中包含了 abc。换句话说,结果匹配是“无论什么东西 abc”。
你能解释一下你最终想要做什么吗?如果您的情况是:(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您可能应该将其作为您自己的单独问题而不是评论发布,尤其是因为它专门针对sed。话虽如此,为了解决您的问题:您可能需要查看 this question 的答案。另请注意,在您的示例中,非贪婪感知解释器将仅返回 two,而不是 two,three
这就是每个正则表达式答案的外观 - 所有部分的示例和解释......
P
Peter Mortensen

正如Jared Ng and @Issun 指出的那样,解决这种正则表达式的关键,如“匹配某个单词或子字符串”或“匹配某个单词或子字符串之后的所有内容”,称为“环视”零长度断言. Read more about them here

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

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

https://i.stack.imgur.com/cxm8d.png


.+?(?=abc) 可复制粘贴的正则表达式更有价值。
排除前导空格怎么样?
可分享的链接也比截图更有价值,开玩笑的,谢谢你的回答
“伊桑”是谁?它指的是什么答案?
Issun 的帐户已不存在。但他们指的是“环顾四周” - 请参阅我在答案中提供的链接。
P
Paul Masri-Stone

解决方案

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

这将匹配

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

正如 OP 所问的那样,即使源字符串包含换行符即使序列以 abc 开头。但是,如果源字符串可能包含换行符,请确保包含多行标志 m

这个怎么运作

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

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

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

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

(?= 称为正向预测。它需要与括号中的字符串匹配,但在它之前停止,因此 (?=abc) 表示“直到但不包括 abc,但 abc 必须存在于源字符串中”。

[\s\S]*(?=abc) 之间的 ? 表示 懒惰(也称为 non greedy)。即停在第一个abc。如果没有这个,如果 abc 出现不止一次,它将捕获直到 final 出现 abc 的每个字符。


奇迹般有效!这应该是公认的答案。
P
Peter Mortensen

您需要环顾一下断言,例如 .+? (?=abc)

请参阅:Lookahead and Lookbehind Zero-Length Assertions

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


P
Peter Mortensen

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

.+?(abc)

例如,在这一行中:

I have this very nice senabctence

选择“abc”之前的所有字符,还包括 abc。

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

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


P
Peter Mortensen

在 Python 中:

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

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

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

P
Peter Mortensen

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

https://i.stack.imgur.com/jgsdL.png

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

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

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

在寻求解决我的问题的帮助后,我以这个 Stack Overflow 问题结束,但我没有找到任何解决方案:(


没有文字版? 🙄
P
Peter Mortensen

这对正则表达式很有意义。

可以从以下正则表达式命令中获得确切的单词:

("(.*?)")/g

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

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

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

然后我们将从该句子中得到“双引号”。


欢迎来到 StackOverflow 并感谢您尝试提供帮助。然而,我发现很难看出这对问题中所述的目标有何帮助。你能详细说明吗?你能把它应用到给定的例子中吗?您似乎专注于处理 ",这对我来说似乎与问题无关。
嗨,我已经解释了如何在特殊字符之间获取单词或句子。在这里,我们的问题也是“直到特殊字符序列的任何内容”。所以我尝试使用双引号并在此处进行了解释。谢谢。
P
Peter Mortensen

我想为 不区分大小写 版本的正则表达式扩展 answer from sidyll

如果您想匹配 abc/Abc/ABC... 不区分大小写,我需要这样做,请使用以下正则表达式。

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

解释:

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

正则表达式的其他解释与 sidyll 指出的相同。


p
proseosoc

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

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

(2) 不匹配空字符串

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

^.+?(?=ABC|$)

P
Peter Mortensen

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

这部分来自 grep 手册:

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

执行 ^[^(abc)] 之类的操作应该可以解决问题。


抱歉,这行不通。将 abc 放在括号中似乎没有任何区别。它们仍被视为“a OR b OR c”。
[^...] 表示“不是方括号内的任何字符,而不是“不是以下标记”,所以这不起作用。
P
Peter Mortensen

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

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


P
Peter Mortensen

尝试这个:

.+?efg

询问:

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

输出:

hijklmn