提问人:callum 提问时间:8/20/2011 最后编辑:Arvind Kumar Avinashcallum 更新时间:10/16/2023 访问量:1270801
如何在正则表达式中匹配“直到此字符序列的任何内容”?
How can I match "anything up until this sequence of characters" in a regular expression?
问:
采用以下正则表达式:.这将匹配字符串开头的任何单个字符,但 a、b 或 c 除外。/^[^abc]/
如果在它后面添加一个 – – 正则表达式将继续将每个后续字符添加到结果中,直到它遇到 、 或 或 。*
/^[^abc]*/
a
b
c
例如,对于源字符串,表达式将匹配到 。"qwerty qwerty whatever abc hello"
"qwerty qwerty wh"
但是,如果我希望匹配的字符串是呢?"qwerty qwerty whatever "
换句话说,我怎样才能将所有内容匹配到(但不包括)确切的序列?"abc"
答:
如果您希望捕获“abc”之前的所有内容:
/^(.*?)abc/
解释:
( )
捕获括号内的表达式,以便使用 、 等进行访问。$1
$2
^
比赛线的起点
.*
不贪婪地匹配任何内容(匹配所需的最小字符数)- [1]?
[1] 之所以需要这样做,是因为否则,在以下字符串中:
whatever whatever something abc something abc
默认情况下,正则表达式是贪婪的,这意味着它将尽可能地匹配。因此,将匹配“无论什么东西,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
标记字符串的末尾,所以像这样的东西应该可以工作:你要寻找任何不以 的迭代结尾的东西,但它必须在末尾$
[[^abc]*]$
abc
此外,如果您使用带有正则表达式的脚本语言(如 PHP 或 JavaScript),它们有一个搜索函数,当它第一次遇到模式时会停止(您可以指定从左侧开始或从右侧开始,或者使用 php,您可以执行内爆来镜像字符串)。
我相信你需要子表达式。您可以对子表达式使用普通括号。()
这部分来自 grep 手册:
反向引用和子表达式
反向引用 \n(其中 n 为单个数字)与子字符串匹配 先前由 正则表达式。
做类似的事情应该可以解决问题。^[^(abc)]
评论
[^...]
表示“不是方括号内的任何字符,而不是”不是下面的标记“,所以这不起作用。
您没有指定您正在使用的正则表达式,但这将 在任何可以被认为是“完整”的最受欢迎的作品中工作。
/.+?(?=abc)/
运作方式
该部分是 (一个或多个
任何事情)。当我们使用时,引擎基本上会匹配一切。
然后,如果正则表达式中有其他内容,它将按步骤返回
尝试匹配以下部分。这是贪婪的行为,
意思是尽可能地满足。.+?
.+
.+
使用时,而不是一次匹配所有并返回
其他条件(如果有),引擎将通过以下方式匹配下一个字符
步骤,直到正则表达式的后续部分匹配(如果有),再次匹配。
这是不贪婪的,意思是尽可能少地匹配
满意。.+?
/.+X/ ~ "abcXabcXabcX" /.+/ ~ "abcXabcXabcX"
^^^^^^^^^^^^ ^^^^^^^^^^^^
/.+?X/ ~ "abcXabcXabcX" /.+?/ ~ "abcXabcXabcX"
^^^^ ^
之后我们有 {contents}
,宽度为零
断言,环顾四周。这种分组结构与其
内容,但不计为匹配的字符(宽度为零)。它
仅当它是否匹配(断言)时才返回。(?=
)
因此,换句话说,正则表达式意味着:/.+?(?=abc)/
尽可能少地匹配任何字符,直到找到“abc”, 不算“ABC”。
评论
.+?
.*
+
*
?
^(?:(?!abc)(?!def).)*
您需要查看断言,例如 ..+? (?=abc)
请参见: Lookahead 和 Lookbehind 零长度断言
请注意,这与 不同。括号内不是字符串 - 每个字符只是其中一种可能性。在括号外,它成为字符串。[abc]
abc
正如 Jared Ng 和 @Issun 所指出的,解决这种正则表达式的关键,例如“将所有内容匹配到某个单词或子字符串”或“匹配某个单词或子字符串之后的所有内容”,称为“环视”零长度断言。在此处阅读有关它们的更多信息。
在您的特定情况下,可以通过积极展望未来来解决:.+?(?=abc)
一张图片胜过千言万语。请参阅屏幕截图中的详细说明。
评论
.+?(?=abc)
可复制粘贴的正则表达式更有价值。
试试这个:
.+?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
这对正则表达式来说是有道理的。
可以从以下正则表达式命令中获取确切的单词:
("(.*?)")/g
在这里,我们可以全局获得属于双引号内的确切单词。
例如,如果我们的搜索文本是
这是“双引号”单词的示例
然后我们将从该句子中得到“双引号”。
评论
"
所以我不得不即兴发挥......一段时间后,我设法达到了我需要的正则表达式:
如您所见,我最多需要在“grp-bps”文件夹之前使用一个文件夹,不包括最后一个破折号。并且要求在“grp-bps”文件夹之后至少有一个文件夹。
复制粘贴的文本版本(将文本的“grp-bps”更改为“grp-bps”):
.*\/grp-bps\/[^\/]+
在寻求帮助来解决我的问题后,我以这个 Stack Overflow 问题结束,但我没有找到任何解决方案:(
评论
在 Python 中:
.+?(?=abc)
适用于单行情况。
[^]+?(?=abc)
不起作用,因为 Python 无法将 [^] 识别为有效的正则表达式。
要使多行匹配正常工作,您需要使用 re.DOTALL 选项,例如:
re.findall('.+?(?=abc)', data, re.DOTALL)
溶液
/[\s\S]*?(?=abc)/
这将匹配
所有内容,直到(但不包括)确切的顺序
"abc"
正如 OP 所要求的那样,即使源字符串包含换行符,即使序列以 abc
开头。但是,如果源字符串可能包含换行符,请务必包含 multiline 标志。m
运作方式
\s
表示任何空格字符(例如空格、制表符、换行符)
\S
指任何非空格字符;即与\s
Together 表示任何角色。这与不匹配换行符几乎相同。[\s\S]
.
.
*
表示前一个标记的出现次数为 0+。我用了它,而不是在源字符串以 .+
abc
(?=
被称为积极展望。它要求与括号中的字符串匹配,但在括号之前停止,因此表示“最多但不包括,但必须存在于源字符串中”。(?=abc)
abc
abc
?
介于 和 之间,表示懒惰(又名非贪婪)。即停在第一个.如果没有这个,它将捕获每个字符,直到最终出现多次。[\s\S]*
(?=abc)
abc
abc
abc
我想扩展 sidyll 对不区分大小写的正则表达式版本的答案。
如果要匹配 abc/Abc/ABC...不区分大小写,我需要这样做,使用以下正则表达式。
.+?(?=(?i)abc)
解释:
(?i) - This will make the following abc match case insensitively.
正则表达式的另一种解释与 sidyll 指出的相同。
如果没有 ABC,则从开始到“ABC”或“Line End”之前匹配
(1) 如果字符串在任何地方都不包含 ABC,则匹配整个字符串
(2) 不匹配空字符串
(不检查带换行符的字符串)
^.+?(?=ABC|$)
您的问题没有指定后续字符序列是否可选,但所有其他答案都假定始终给出该序列。所以这里有一个,如果序列是可选的。
例如,如果将代码匹配到行注释(如 或),则行注释本身可能是可选的,但可能仍希望匹配前面的代码。foo # ...
foo // ...
在这种情况下,我会使用(或行注释:或)。^(?:(?!abc).)*
^(?:(?!#).)*
^(?:(?!\/\/).)*
说明:
标记行的开头。 是一个非捕获组,因为常规组会额外捕获组中的最后一个匹配字母,这是我们不需要的。
在组内,我们使用负前瞻和 ,因此除了特定序列外,所有内容都匹配。这重复 0 到无限次。如果只想匹配非空字符串,请改用。^
(?:)
(?!)
.
*
+
评论
match but not including
"qwerty qwerty whatever "
"qwerty qwerty whatever abc"
do string.split('abc')[0]