采用这个正则表达式:/^[^abc]/
。这将匹配字符串开头的任何单个字符,a、b 或 *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"
。
do string.split('abc')[0]
。当然不是这个问题的官方答案,但我发现它比正则表达式更直接。
您没有指定您正在使用哪种风格的正则表达式,但这将适用于任何可以被认为是“完整”的最流行的正则表达式。
/.+?(?=abc)/
这个怎么运作
.+?
部分是 .+
的非贪婪版本(任何一个或多个)。当我们使用 .+
时,引擎将基本匹配所有内容。然后,如果正则表达式中有其他内容,它将返回尝试匹配以下部分的步骤。这就是贪婪的行为,意思是尽可能的满足。
使用 .+?
时,引擎将逐步匹配下一个字符,直到匹配正则表达式的后续部分(如果有,再次匹配),而不是一次匹配所有条件并返回其他条件(如果有)。这是un-greedy,意思是匹配尽可能少的满足。
/.+X/ ~ "abcXabcXabcX" /.+/ ~ "abcXabcXabcX"
^^^^^^^^^^^^ ^^^^^^^^^^^^
/.+?X/ ~ "abcXabcXabcX" /.+?/ ~ "abcXabcXabcX"
^^^^ ^
之后我们有 (?=
{contents}
)
,一个零宽度断言,一个环顾。此分组结构与其内容匹配,但不计为匹配的字符(零宽度)。它仅在匹配与否时才返回(assertion)。
因此,换句话说,正则表达式 /.+?(?=abc)/
意味着:
尽可能少地匹配任何字符,直到找到“abc”,不计算“abc”。
如果您要捕获“abc”以下的所有内容:
/^(.*?)abc/
解释:
( )
捕获括号内的表达式,以便使用 $1
、$2
等进行访问。
^
匹配行首
.*
匹配任何内容,?
非贪婪(匹配所需的最少字符数)- [1]
[1] 需要这样做的原因是,否则,在以下字符串中:
whatever whatever something abc something abc
默认情况下,正则表达式是 greedy,这意味着它会尽可能匹配。因此 /^.*abc/
将匹配“无论什么东西 abc 东西”。添加非贪婪量词 ?
使正则表达式仅匹配“无论什么”。
sed
似乎不支持非贪婪匹配,也不支持环视 ((?=...)
)。我还可以做些什么?示例命令:echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"
返回 two,three, FOUR FIVE
,但我希望 two,three
...
two
,而不是 two,three
。
正如Jared Ng and @Issun 指出的那样,解决这种正则表达式的关键,如“匹配某个单词或子字符串”或“匹配某个单词或子字符串之后的所有内容”,称为“环视”零长度断言. Read more about them here。
在您的特定情况下,可以通过积极展望来解决:.+?(?=abc)
一张图片胜过千言万语。请参阅屏幕截图中的详细说明。
https://i.stack.imgur.com/cxm8d.png
.+?(?=abc)
可复制粘贴的正则表达式更有价值。
解决方案
/[\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
的每个字符。
您需要环顾一下断言,例如 .+? (?=abc)
。
请参阅:Lookahead and Lookbehind Zero-Length Assertions
请注意,[abc]
与 abc
不同。在括号内它不是一个字符串 - 每个字符只是一种可能性。在括号之外,它成为字符串。
对于 Java 中的正则表达式,我也相信大多数正则表达式引擎,如果你想包含最后一部分,这将起作用:
.+?(abc)
例如,在这一行中:
I have this very nice senabctence
选择“abc”之前的所有字符,还包括 abc。
使用我们的正则表达式,结果将是:I have this very nice senabc
测试一下:https://regex101.com/r/mX51ru/1
在 Python 中:
.+?(?=abc)
适用于单行情况。
[^]+?(?=abc)
不起作用,因为 python 不将 [^] 识别为有效的正则表达式。要进行多行匹配,您需要使用 re.DOTALL 选项,例如:
re.findall('.+?(?=abc)', data, re.DOTALL)
所以我不得不即兴发挥......一段时间后,我设法达到了我需要的正则表达式:
https://i.stack.imgur.com/jgsdL.png
如您所见,我需要在“grp-bps”文件夹之前最多一个文件夹,不包括最后一个破折号。并且要求在“grp-bps”文件夹之后至少有一个文件夹。
复制粘贴的文本版本(为您的文本更改“grp-bps”):
.*\/grp-bps\/[^\/]+
在寻求解决我的问题的帮助后,我以这个 Stack Overflow 问题结束,但我没有找到任何解决方案:(
这对正则表达式很有意义。
可以从以下正则表达式命令中获得确切的单词:
("(.*?)")/g
在这里,我们可以在全局范围内获得属于双引号内的确切单词。
例如,如果我们的搜索文本是
这是“双引号”单词的示例
然后我们将从该句子中得到“双引号”。
"
,这对我来说似乎与问题无关。
我想为 不区分大小写 版本的正则表达式扩展 answer from sidyll。
如果您想匹配 abc/Abc/ABC... 不区分大小写,我需要这样做,请使用以下正则表达式。
.+?(?=(?i)abc)
解释:
(?i) - This will make the following abc match case insensitively.
正则表达式的其他解释与 sidyll 指出的相同。
匹配从开始到“ABC 之前”或“行结束”(如果没有 ABC)
(1) 如果字符串在任何地方都不包含 ABC,则匹配整个字符串
(2) 不匹配空字符串
(不检查带有换行符的字符串)
^.+?(?=ABC|$)
我相信你需要子表达式。您可以对子表达式使用普通的 ()
括号。
这部分来自 grep 手册:
反向引用和子表达式 反向引用 \n,其中 n 是单个数字,匹配先前由正则表达式的第 n 个带括号的子表达式匹配的子字符串。
执行 ^[^(abc)]
之类的操作应该可以解决问题。
[^...]
表示“不是方括号内的任何字符,而不是“不是以下标记”,所以这不起作用。
$
标记了字符串的结尾,所以这样的事情应该可以工作:[[^abc]*]$
您在 abc
的任何迭代中寻找任何没有结束的东西,但它必须到最后
此外,如果您使用带有正则表达式的脚本语言(如 PHP 或 JavaScript),它们有一个搜索功能,当它第一次遇到模式时会停止(您可以指定从左侧开始或从右侧开始,或者使用 php,你可以做一个内爆来镜像字符串)。
尝试这个:
.+?efg
询问:
select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;
输出:
hijklmn
.+?
和.*
有什么区别?+
表示 1 或更多,其中*
表示 0 或更多。?
的包含/排除将使其变得贪婪或非贪婪。^(?:(?!abc)(?!def).)*
,您可以链接以排除您不想要的模式,即使模式确实存在,它仍会根据需要抓取所有内容不存在