RegEx:在引号之间抓取值

我的值是这样的:

"Foo Bar" "Another Value" something else

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

552649 次浏览

一般来说,下面的正则表达式片段就是你要找的:

"(.*?)"

这使用了非贪婪的*?运算符来捕获下一个双引号之前的所有内容。然后,使用特定于语言的机制提取匹配的文本。

在Python中,你可以这样做:

>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']

我认为:

"([^"]*)"
(^”)是除''
外的任何字符的正则表达式 我在非贪婪多操作符上使用这个的原因是我必须不断查找以确保我得到正确的

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

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

它还支持嵌套引号。

对于那些想要更深入地解释它是如何工作的人来说,下面是来自用户ephemient的解释:

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

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

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

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

这个版本

  • 转义引号的说明
  • < p >控制回溯

    /(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
    

对我来说是这样的:

|([\'"])(.*?)\1|i

我曾经用过这样一个句子:

preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);

而且效果很好。

我能够创建这个正则表达式来满足我的需求。

我需要匹配一个包含引号的特定值。它必须是完全匹配的,没有部分匹配可以触发命中

如。“test”不能与“test2”匹配。

reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."

猎人

我喜欢《Axeman》更广阔的版本,但也遇到了一些问题(游戏邦注:例如它并不匹配

foo "string \\ string" bar

foo "string1"   bar   "string2"

正确,所以我试图修复它:

# opening quote
(["'])
(
# repeat (non-greedy, so we don't span multiple strings)
(?:
# anything, except not the opening quote, and not
# a backslash, which are handled separately.
(?!\1)[^\\]
|
# consume any double backslash (unnecessary?)
(?:\\\\)*
|
# Allow backslash to escape characters
\\.
)*?
)
# same character as opening quote
\1
string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)

试试这个,就像一个魅力!!

\表示跳过字符

很晚才回答,却喜欢回答

(\"[\w\s]+\")

http://regex101.com/r/cB0kB8/1 < a href = " http://regex101.com/r/cB0kB8/1 " > < / >

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

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

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

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

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

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

Perl像:

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

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

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

ECMA脚本:

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

POSIX扩展:

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

或者仅仅是:

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

上面的模式(["'])(?:(?=(\\?))\2.)*?\1可以完成这项工作,但我担心它的性能(它并不差,但可以更好)。我的比它快20%。

模式"(.*?)"是不完整的。我对阅读这篇文章的人的建议是不要使用它!!

例如,它不能捕获很多字符串(如果需要,我可以提供一个详尽的测试用例),如下所示:

$string = '你好吗?我很好,谢谢你’;

其余的都和上面那个一样“好”。

如果你真的关心性能和精度,那么就从下面的开始:

/(['"])((\\\1|.)*?)\1/gm

在我的测试中,它涵盖了我遇到的每一个字符串,但如果你发现一些不工作的东西,我很乐意为你更新它。

在在线正则表达式测试器中检查我的模式

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

下面是只返回< em > < / em >之间的值引号的RegEx(正如提问者所要求的):

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

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

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

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

这两个(捕获组#2的使用值):

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

-

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

更多的答案!这是我使用的解决方案

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

< br > < p > TLDR; 将词图标替换为你在引用中寻找的东西,瞧!< / p >
它的工作方式是查找关键字,而不关心引号之间的其他内容。 如:< br > id="fb-icon" < br > id="icon-close" < br > id="large-icon-close" < br > 正则表达式查找引号"
然后它寻找任何可能的不是"
的字母组 直到找到icon
和任何可能不是"
的字母组 然后查找结束"

特别的是,这些答案都不会产生一个正则表达式,其中返回的匹配是所要求的引号内的文本。MA-Madden尝试了,但只获得了内部匹配,而不是整个匹配。一种实际的方法是:

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

这方面的例子可以在这个演示https://regex101.com/r/Hbj8aP/1中看到

这里的关键是开始时的正向向后看(?<=)和结束时的正向向前看(?=)。向后查找是在当前字符后面查找引用,如果找到了就从那里开始,然后向前查找是在字符前面查找引用,如果找到了就停在那个字符上。后面的追溯组(["'])被括在括号中,为开头找到的任何报价创建一个组,然后在结尾的超前追溯(?=\1)中使用这个组,以确保它只在找到相应的报价时才停止。

唯一的另一个复杂之处在于,由于前向查询实际上并不使用结束引号,它将被开始后向查询再次找到,这将导致匹配同一行上结束引号和开始引号之间的文本。在开头引用(["']\b)上设置单词边界有助于这一点,尽管理想情况下,我希望跳过前置式,但我认为这是不可能的。中间允许转义字符的部分直接取自亚当的回答。

如果你试图查找只有特定后缀的字符串,比如点语法,你可以尝试这样做:

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

其中.localized是后缀。

例子:

print("this is something I need to return".localized + "so is this".localized + "but this is not")

它将捕获"this is something I need to return".localized"so is this".localized,但不捕获"but this is not"

仅限微软VBA编码器 one子集的补充答案使用库Microsoft VBScript Regular Expressions 5.5,并给出以下代码

Sub TestRegularExpression()


Dim oRE As VBScript_RegExp_55.RegExp    '* Tools->References: Microsoft VBScript Regular Expressions 5.5
Set oRE = New VBScript_RegExp_55.RegExp


oRE.Pattern = """([^""]*)"""




oRE.Global = True


Dim sTest As String
sTest = """Foo Bar"" ""Another Value"" something else"


Debug.Assert oRE.test(sTest)


Dim oMatchCol As VBScript_RegExp_55.MatchCollection
Set oMatchCol = oRE.Execute(sTest)
Debug.Assert oMatchCol.Count = 2


Dim oMatch As Match
For Each oMatch In oMatchCol
Debug.Print oMatch.SubMatches(0)


Next oMatch


End Sub

与亚当的答案不同,我有一个简单但有效的答案:

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

如果你想要得到引号中的内容,只需添加圆括号:

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

然后$1匹配引号字符,$2匹配内容字符串。

我喜欢欧根·米哈列斯库的解决方案来匹配引号之间的内容,同时允许转义引号。然而,我发现了一些转义的问题,并提出了以下正则表达式来解决它们:

(['"])(?:(?!\1|\\).|\\.)*\1

它做到了这一点,而且仍然非常简单,易于维护。

< >强演示< / >强(带有更多的测试用例;请随意使用并扩展它)。


< p > <子> PS:如果你只想要内容之间的在完整匹配中引用($0),并且不怕性能损失,请使用:

(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)

不幸的是,没有引号作为锚,我不得不添加一个边界\b,它不能很好地处理开始引号后的空格和非单词边界字符。

或者,修改初始版本,只需添加一个组,并提取字符串形式$2:

(['"])((?:(?!\1|\\).|\\.)*)\1
PPS:如果你只关注效率,使用卡西米尔和希波吕特的解;这是一个很好的例子。 < / sub > < / p >

以上所有的答案都很好....除了他们不支持所有的unicode字符!在ECMA脚本(Javascript)

如果你是Node用户,你可能想要支持所有unicode字符的可接受答案的修改版本:

/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu

在这里试试。

我的解决方案如下

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

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

解释:

(["'])→匹配到'",并在找到匹配后将其存储在反向引用\1

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

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

(?![^\s])→负前向以确保在前一个匹配之后不应该有任何非空格字符