/"[^"]+"/ # match quote, then everything that's not a quote, then a quote
或者/".+?"/ # match quote, then *anything* (non-greedy), then a quote
假设这个问题中空字符串(即“”)不是一个问题。在我看来(我不是正则表达式的新手,但肯定不是专家),这些表达式将是等效的。更新:经过反思,我认为将“+”字符更改为“*”将正确处理空字符串。
/"[^"]+"/ # match quote, then everything that's not a quote, then a quote
或者/".+?"/ # match quote, then *anything* (non-greedy), then a quote
假设这个问题中空字符串(即“”)不是一个问题。在我看来(我不是正则表达式的新手,但肯定不是专家),这些表达式将是等效的。你应该使用第一种方法,因为第二种方法是不好的实践。考虑到后续的开发人员需要查找后面跟着感叹号的字符串,那么他应该使用:
"[^"]*"!
或:".*?"!
当主语存在时,就会出现差异:
"one" "two"!
第一个正则表达式匹配:
"two"!
当第二个正则表达式匹配时:
"one" "two"!
尽可能具体,使用否定字符类。与 .* 不同,[^"]* 可跨越多行,除非使用单行模式,否则 [^"\n]* 也会排除换行符。
至于回溯,第二个正则表达式在匹配每个字符串的每个字符时都会回溯。如果缺少闭合引号,则两个正则表达式都将通过整个文件进行回溯。只有它们回溯的顺序不同。因此,从理论上讲,第一个正则表达式更快。但实际上,你不会注意到任何差别。
更加复杂,但它处理了转义引号和转义反斜杠(转义反斜杠后面跟着引号不是问题)
/(["'])((\\{2})*|(.*?[^\\](\\{2})*))\1/
示例:
"hello\"world" 匹配 "hello\"world"
"hello\\"world" 匹配 "hello\\"
我建议:
([\"'])(?:\\\1|.)*?\1
之所以选择这个方法,是因为它能处理转义引号字符并允许单引号和双引号都作为引号。我还建议查看这篇深入探讨此问题的文章:http://blog.stevenlevithan.com/archives/match-quoted-string
然而,除非你有严重的性能问题或不能确定是否存在嵌套引号,否则请使用更简单和易读的方法:
/".*?"/
我必须承认,非贪婪模式不是基本的类Unix风格的“ed”正则表达式,但它们变得越来越普遍。我仍然不习惯像(?:stuff)这样的组操作符。
我认为第二个更好,因为当缺少终止符"
时会更快地失败。第一个将在字符串上回溯,这是一种潜在的昂贵操作。如果您使用的是Perl 5.10,则另一种正则表达式可能是/"[^"]++"/
,它传达与版本1相同的含义,但与版本2一样快。
我会选择第二个选项,因为它更易读。但是我仍然希望匹配空字符串,所以我会使用:
/".*?"/
/"[^"]+"/ # 匹配引号,然后是除引号以外的所有内容,最后是一个引号
只匹配最小的一对匹配引号-非常好,大多数情况下这就是您所需要的。 但是,如果您有嵌套的引号,并且您对最大的匹配引号(或所有匹配的引号)感兴趣,则处于更加复杂的情况。从性能角度来看(长字符串上的重型、长时间运行的循环),我可以想象
"[^"]*"
".*?"
因为后者需要在每一步进行额外的检查:查看下一个字符。前者可以无意识地在字符串上滚动。
正如我所说,在实际情况下,这几乎不会被注意到。因此,我会选择第二种方法(如果我的当前正则表达式支持它),因为它更易读。否则就用第一种方法。
考虑到我直到今天才知道“*?”的事情,而我已经使用正则表达式20多年了,我会赞成第一个。它确实清楚地表明了你想要做什么-你想匹配一个不包含引号的字符串。
Search for double-quote
add double-quote to group
for each char:
if double-quote:
break
add to group
add double-quote to group
是做一些更复杂的回溯相关编程吗?