如果我试图将引号分隔的字符串与正则表达式匹配,则以下哪个是"更好"(其中"更好"意味着更高效且不太可能做出意外事情):
/"[^"]+"/ # 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相同的含义,但与第二版一样快.