当前位置:  开发笔记 > 编程语言 > 正文

RegEx:在引号之间抓取值

如何解决《RegEx:在引号之间抓取值》经验,为你挑选了9个好方法。

我有这样的价值:

"Foo Bar" "Another Value" something else

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



1> Adam..:

我一直在使用以下成功:

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

它也支持嵌套引号.

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

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


这也有效:`(["'])(\\ ?.)*?\ 1`更容易阅读.
@steve:这也会错误地匹配"foo".前瞻性技巧使```量词占有欲(即使正则表达式不支持`?+`语法或原子分组)
这将返回包括匹配引号的值.根据要求,是否没有机会只返回引号之间的**内容?
将前瞻性作为所有格量词完全没有必要且令人困惑。只需使用替代:`([“”])(?:\\。| [^^ \])*?\ 1`

2> Greg Hewgill..:

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

"(.*?)"

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

在Python中,您可以这样做:

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


这很好,但它不处理带有转义引号的字符串.例如,"你好"世界"`
@robbyt我知道答案有点晚了,但负面的背后呢?' "(.*?(?
3> Martin York..:

我会去:

"([^"]*)"

[^"]是除任何字符正则表达式' " "
我用这个在非贪婪多的运营商的原因是,我要继续找,最多只是为了确保我得到它正确的.


这节省了我的理智.在.NET的RegEx实现中,"(.*?)"没有所需的效果(它不起作用非贪婪),但"([^"]*)"确实如此.

4> Casimir et H..:

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

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

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

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

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

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

Perl喜欢:

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

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

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

ECMA脚本:

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

POSIX扩展:

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

或者干脆:

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



5> IrishDubGuy..:

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

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

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

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

唯一的另一个困难是因为超前,实际上并不消耗最终报价,将再次开始回顾后引起结束和开始在同一线路报价进行匹配之间的文本中.在开头引号(["']\b)上加上一个单词边界有助于此,虽然理想情况下我想要超越前瞻但我不认为这是可能的.这个位允许中间的逃脱角色我直接从亚当的回答中获取.



6> Martin Schne..:

接受的答案的RegEx返回值,包括其周围的引号:"Foo Bar""Another Value"匹配.

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

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

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

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

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

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

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

-

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



7> Suganthan Ma..:

一个很晚的答案,但想回答

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

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



8> Axeman..:

这个版本

转帐报价的帐户

控制回溯

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



9> Eugen Mihail..:

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

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

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

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

剩下的就像上面那样"好".

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

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

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

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

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有