我的值是这样的:

"Foo Bar" "Another Value" something else

什么正则表达式将返回括在引号中的值(例如Foo Bar和Another Value)?


当前回答

接受的答案的RegEx返回值,包括它们的寻源引号:“Foo Bar”和“Another Value”作为匹配。

下面是RegEx,它只返回引号之间的值(正如提问者所要求的那样):

仅使用双引号(使用捕获组#1的值):

"(.*?[^\\])"

仅使用单引号(使用捕获组#1的值):

'(.*?[^\\])'

Both(使用捕获组#2的值):

([']) "(. *? 1 \ [^ \ \])

-

全部支持转义和嵌套引号。

其他回答

我一直在使用以下方法并取得了巨大的成功:

(["'])(?:(?=(\\?))\2.)*?\1

它还支持嵌套引号。

对于那些想要更深入地解释这是如何工作的人,这里是用户ephemerent的解释:

([""'])匹配引号;((?=(\\?))\2.)如果存在反斜杠,吞噬它,无论是否发生,匹配一个字符;* ?匹配多次(非贪婪,如不吃结尾引号);\1匹配相同的报价,是用于开幕。

echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'

这将导致:>Foo Bar<><>但这<

在这里,为了清晰起见,我显示了><'s之间的结果字符串,也使用了这个sed命令的非贪婪版本,我们首先抛出' 's之前和之后的垃圾,然后用' ' 's之间的部分替换它,并用><'s包围它。

这个版本

转义引号的说明 控制回溯 /(["'])((?:(?!\ 1 )[^\\]|(?:\\\\)*\\[^\\])*)\ 1 /

我的解决方案如下

(\[‘])。* 1 (? ! [s ^ \])

演示链接:https://regex101.com/r/jlhQhV/1

解释:

(["'])->匹配'或',一旦找到匹配,将其存储在反向引用\1中

.* ->贪婪的方法继续匹配所有内容0次或更多次,直到它在字符串末尾遇到'或"。遇到这种状态后,正则表达式引擎返回到上一个匹配字符,此时正则表达式结束,将移动到下一个正则表达式。

\1 ->匹配先前与第一个捕获组匹配的字符或字符串。

(?![^\s]) ->负前向,确保在之前的匹配之后不应该有任何非空格字符

让我们看看处理转义引号的两种有效方法。这些模式不是为了简洁或美观而设计的,而是为了高效。

这些方法使用第一个字符区分快速查找字符串中的引号,而不需要进行替换。(这个想法是快速丢弃不是引号的字符,以测试交替的两个分支。)

引号之间的内容用一个展开的循环(而不是重复的交替)来描述,这样也更有效率:[^"\\]*(?:\\.[^"\\]*)*

显然,要处理没有平衡引号的字符串,可以使用所有格量词:[^"\\]*+(?:\\.[^"\\]*)*+或模仿它们的替代方法,以防止太多回溯。你也可以选择一个带引号的部分可以是一个开始引号,直到下一个(非转义)引号或字符串的结尾。在这种情况下,没有必要使用所有格量词,你只需要使最后一个引用是可选的。

注意:有时引号不是用反斜杠转义,而是通过重复引号转义。在这种情况下,内容子模式看起来像这样:[^"]*(?:""[^"]*)*

这些模式避免使用捕获组和反向引用(我的意思是(["']).....\1),并使用简单的替换,但在factor开头使用["']。

Perl像:

["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')

(注意,(?s:…)是一个语法糖,用于在非捕获组中打开dotall/单线模式。如果不支持此语法,您可以轻松地为所有模式打开此模式或将点替换为[\s\ s])

(这种模式的编写方式完全是“手工驱动的”,没有考虑到最终的引擎内部优化)

ECMA脚本:

(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')

POSIX扩展:

"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'

或者仅仅是:

"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'