RegEx:在引号之间抓取值

时间:2008-10-05 04:22:07

标签: regex

我有这样的价值:

"Foo Bar" "Another Value" something else

什么正则表达式会返回引号中包含的值(例如Foo BarAnother Value)?

20 个答案:

答案 0 :(得分:291)

我一直在使用以下内容取得巨大成功:

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

它也支持嵌套引号。

对于那些想要更深入解释其工作原理的人,以下是用户ephemient的解释:

  

([""'])匹配报价; ((?=(\\?))\2.)如果存在反斜杠,则吞噬它,以及是否发生这种情况,匹配一个字符; *?匹配多次(非贪婪,不吃关闭报价); \1匹配用于打开的相同引用。

答案 1 :(得分:278)

通常,您正在寻找以下正则表达式片段:

"(.*?)"

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

在Python中,您可以这样做:

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

答案 2 :(得分:78)

我会选择:

"([^"]*)"

[^“] 是除”'之外的任何字符的正则表达式 我使用它比非贪婪的许多操作员的原因是我必须继续查看,以确保我得到它正确。

答案 3 :(得分:23)

让我们看看两种处理转义报价的有效方法。这些图案不是简洁而美观,而是高效。

这些方法使用第一个字符区分来快速查找字符串中的引号,而无需更改成本。 (想法是在没有测试交替的两个分支的情况下快速丢弃不是引号的字符。)

引号之间的内容用展开的循环(而不是重复的循环)来描述,以提高效率:[^"\\]*(?:\\.[^"\\]*)*

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

注意:有时引号不会使用反斜杠进行转义,而是重复引用。在这种情况下,内容子模式如下所示:[^"]*(?:""[^"]*)*

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

Perl喜欢:

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

(请注意,(?s:...)是在非捕获组内打开dotall / singleline模式的语法糖。如果不支持此语法,您可以轻松地为所有模式打开此模式或用[\s\S]

替换点

(这种模式的编写方式完全是#34;手动驱动&#34;并且没有考虑最终的引擎内部优化)

ECMA脚本:

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

POSIX扩展:

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

或简单地说:

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

答案 4 :(得分:11)

特别是,这些答案都没有产生正则表达式,其中返回的匹配是引号内的文本,这就是要求的内容。 MA-Madden尝试但仅仅将内线比赛作为一个被捕获的组而不是整场比赛。实际做到这一点的一种方法是:

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

此示例可以在此演示https://regex101.com/r/Hbj8aP/1

中看到

这里的关键是开始时的正面观察(?<=)和结束时的正向前瞻(?=)。 lookbehind正在查看当前字符后面以检查引用,如果找到则从那里开始,然后前瞻是检查前面的字符以获得引用,如果发现该字符停止。将lookbehind组(["'])包装在括号中,以便为在开头找到的任何引号创建一个组,然后在最后的前瞻(?=\1)中使用它,以确保它只在找到时停止相应的报价。

唯一的另一个复杂因素是,因为前瞻实际上并没有消耗结束引用,所以将通过起始lookbehind再次找到它,这会导致同一行上的结尾和起始引号之间的文本匹配。在开头引号(["']\b)上加上一个单词边界有助于此,虽然理想情况下我想要超越前瞻但我不认为这是可能的。这个位允许中间的逃脱角色我直接从亚当的回答中获取。

答案 5 :(得分:10)

接受答案的RegEx会返回包含其周围引号的值:"Foo Bar""Another Value"作为匹配。

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

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

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

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

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

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

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

-

所有支持转义和嵌套引号。

答案 6 :(得分:8)

答案非常晚,但想回答

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

http://regex101.com/r/cB0kB8/1

答案 7 :(得分:6)

此版本

  • 说明转义报价
  • 控制回溯

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

答案 8 :(得分:5)

上面的模式(["'])(?:(?=(\\?))\2.)*?\1完成了工作,但我担心它的表现(它不错但可能更好)。我的低于它的速度快〜20%。

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

例如,它无法捕获许多字符串(如果需要,我可以提供详尽的测试用例),如下所示:

  

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

其余的与上面的一样“好”。

如果您真的关心性能和精度,请从下面开始:

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

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

Check my pattern in an online regex tester

答案 9 :(得分:4)

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

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

TLDR;
图标一词替换为您在报价中所寻找的内容并瞧!

这种方式的工作方式是查找关键字,并不关心引号之间的其他内容。 EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
正则表达式寻找引号"
然后它会查找不是"的任何可能的字母组 直到它找到icon
以及任何可能不是"的字母组 然后它会查找结束"

答案 10 :(得分:4)

我喜欢Eugen Mihailescu's solution以匹配引号之间的内容,同时允许转义引号。但是,我发现了一些转义问题,并提出了以下正则表达式来修复它们:

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

它可以解决问题,但仍然非常简单易于维护。

Demo(还有一些测试用例;随意使用它并对其进行扩展)。

PS:如果您只想在完全匹配($0)中的之间引用内容,并且不怕性能损失,请使用:

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

PPS:如果您只关注效率,请使用Casimir et Hippolyte's solution;这是一个很好的。

答案 11 :(得分:3)

我喜欢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

答案 12 :(得分:2)

string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)

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

\表示跳过字符

答案 13 :(得分:1)

来自Greg H.我能够创建这个正则表达式以满足我的需求。

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

e.g。 “test”无法匹配“test2”。

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

亨特

答案 14 :(得分:1)

Microsoft VBA编码器子集的补充答案之一使用库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

答案 15 :(得分:1)

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

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

如果你想在这样的引号中获取内容,只需添加括号:

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

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

答案 16 :(得分:0)

我为这个工作过:

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

我用过这样的句子:

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

并且效果很好。

答案 17 :(得分:0)

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

这将导致:&gt; Foo Bar&lt;&gt;&lt;&gt;但此&lt;

为了清楚起见,我在&gt;&lt;'s之间显示了结果字符串,同样使用非贪婪版本和这个sed命令我们首先抛出那个“”之前和之后的垃圾,然后将其替换为“和”之间的部分并且通过&gt;&lt; ss围绕它。

答案 18 :(得分:0)

如果您正在尝试查找仅具有特定后缀的字符串,例如点语法,则可以尝试以下操作:

\"([^\"]*?[^\"]*?)\".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"

答案 19 :(得分:0)

上面的所有答案都很好。...除了它们不支持所有unicode字符!,在ECMA脚本(Javascript)中

如果您是Node用户,则可能需要支持所有Unicode字符的接受答案的修改版:

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

尝试here