正则expression式:在引号之间抓取值

我有这样的价值:

"Foo Bar" "Another Value" something else 

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

我一直在使用以下巨大的成功:

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

它也支持嵌套的引号。

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

([""'])匹配一个报价; ((?=(\\?))\2.)如果反斜杠存在,将其吞噬,并且是否发生这种情况,匹配一个字符; *? 匹配多次(非贪婪,至于不吃最后的报价); \1匹配用于打开的相同报价。

一般来说,下面的正则expression式片段就是你正在寻找的东西:

 "(.*?)" 

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

在Python中,你可以这样做:

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

我会去的:

 "([^"]*)" 

[^“]是除了” 之外的任何字符的正则expression式
我在非贪心许多操作符上使用这个的原因是,为了确保正确,我必须继续查找。

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

这些方法使用第一个字符歧视来快速查找string中的引号,而不需要交替的成本。 (这个想法是在没有testing交替的两个分支的情况下快速丢弃不是引号的字符。)

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

显然,要处理没有均衡引号的string,您可以使用所有格量词: [^"\\]*+(?:\\.[^"\\]*)*+或者一个解决方法来模拟它们,防止回溯太多。 您也可以select引用的部分可以是开始引号,直到下一个(未转义的)引号或string结尾。 在这种情况下,不需要使用占有量词,只需要使最后一个引用是可选的。

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

模式避免使用捕获组和反向引用(我的意思是像(["']).....\1 ),并使用一个简单的替代,但在开始时使用["'] ,因子。

Perl像:

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

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

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

ECMA脚本:

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

POSIX扩展:

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

或者干脆:

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

答案很晚,但喜欢回答

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

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

这个版本

  • 帐户逃脱报价
  • 控制回溯

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

上面的模式(["'])(?:(?=(\\?))\2.)*?\1做了这个工作,但是我担心它的performance(这不坏,但可能会更好)。低于它快20%。

模式"(.*?)"只是不完整的。 我的build议,每个人阅读这只是不要使用它!

例如,它不能捕获许多string(如果需要,我可以提供一个详尽的testing用例),如下所示:

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

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

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

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

在我的testing中,它覆盖了我遇到的每一个string,但是如果你发现一些不起作用的东西,我会很乐意为你更新它。

在线正则expression式testing中检查我的模式 。

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

已接受答案的正则expression式返回值包括它们的引用引号: "Foo Bar""Another Value"作为匹配。

这里是RegEx,它只返回两个引号之间 (正如提问者所要求的那样):

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

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

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

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

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

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

所有的支持逃脱和嵌套报价。

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

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

TLDR;
用你在报价中寻找的单词replace图标 ,瞧!


它的工作方式是寻找关键字,并不在乎引号之间的其他内容。 例如:
id="fb-icon"
id="icon-close"
id="large-icon-close"
正则expression式寻找一个引号"
那么它寻找任何可能的一组字母那不是"
直到findicon
以及任何可能的不是"
然后它寻找一个closures"

Greg H.我能够创build这个正则expression式来满足我的需求。

我需要匹配一个特定的值,通过在报价中被限定。 它必须是一个完整的匹配,没有部分匹配可能会触发一个命中

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

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

猎人

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

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

\表示跳过字符

对我来说这是一个:

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

我用过这样一句话:

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

而且效果很好。

奇怪的是,这些答案都没有产生一个正则expression式,其中返回的匹配是引号内的文本,这就是要求的。 MA-Madden尝试,但只获得内部比赛作为一个被捕获的组,而不是整场比赛。 实际做到这一点的一个方法是:

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

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

这里的关键是开始时的积极向后看( ?<= )和结束时的积极向前看( ?= )。 后视是看当前字符后面检查一个报价,如果find,然后从那里开始,然后向前检查字符提前报价,如果发现停止该字符。 lookbehind组( ["'] )用方括号括起来,以便在开始时发现引用中的任何引用,然后在结尾lookahead (?=\1)处使用它,以确保只有当它find相应的报价。

唯一的另一个复杂因素是,因为前瞻并没有真正消耗结束引号,所以它将会被同样的行中结尾和开始引号之间的文本匹配。 在开头引号( ["']\b )上加上一个单词边界是有帮助的,尽pipe理想情况下我想移过去,但是我不认为这是可能的。直接从亚当的回答中拿出来。

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

这将导致:> Foo Bar <> <>,​​但是这个<

在这里,为了清楚起见,我在<>之间显示了结果string,在这个sed命令中也使用了非贪婪版本,我们首先在这个“”之前和之后扔掉垃圾,然后用“并且围绕这个> <的。