【发布时间】:2016-09-19 13:50:03
【问题描述】:
我想解析一个输入字符串并确定它是否包含被双引号 (") 包围的字符序列。
字符序列本身不允许包含更多的双引号,除非它们被反斜杠转义,例如:\"。
为了让事情变得更复杂,反斜杠可以自己转义,如下所示:\\。因此,不会转义前面有两个(或任何偶数个)反斜杠 (\\") 的双引号。
更糟糕的是,允许使用单个非转义反斜杠(即后跟既不" 也不\)。
我正在尝试使用 Python 的 re 模块来解决这个问题。
module documentation 告诉我们有关管道运算符A|B:
扫描目标字符串时,从左到右尝试由
'|'分隔的RE。当一个模式完全匹配时,该分支被接受。这意味着一旦A匹配,B将不会被进一步测试,即使它会产生更长的整体匹配。换句话说,'|'运算符永远不会贪婪。
但是,这并没有像我预期的那样工作:
>>> import re
>>> re.match(r'"(\\[\\"]|[^"])*"', r'"a\"')
<_sre.SRE_Match object; span=(0, 4), match='"a\\"'>
这个正则表达式的想法是首先检查转义字符(\\ 或 \"),只有在没有找到时,才检查任何不是 " 的字符(但它可能是单个 @987654340 @)。
这可以发生任意次数,并且必须用文字 " 字符包围。
我希望字符串 "a\" 根本不匹配,但显然它匹配。
我希望\" 匹配A 部分和B 部分不被测试,但显然它是。
我真的不知道在这种情况下回溯是如何工作的,但是有没有办法避免它?
我想如果我在单独的步骤中首先检查初始 " 字符(并将其从输入中删除),它会起作用。
然后我可以使用以下正则表达式来获取字符串的内容:
>>> re.match(r'(\\[\\"]|[^"])*', r'a\"')
<_sre.SRE_Match object; span=(0, 3), match='a\\"'>
这将包括转义的引号。由于没有结束引号,我会知道总体而言,给定的字符串不匹配。
我必须这样做还是可以用一个正则表达式解决这个问题而无需额外的手动检查?
在我的实际应用程序中,"-enclosed 字符串只是较大模式的一部分,因此我认为在单个正则表达式中一次完成所有操作会更简单。
我发现了类似的问题,但那些不认为单个非转义反斜杠可以是字符串的一部分:regex to parse string with escaped characters、Parsing for escape characters with a regular expression。
【问题讨论】:
-
看这个:
"(?:[^\\"]|\\.)*"-->"[^"\\]*(?:\\.[^"\\]*)*" -
谢谢,效果很好!你说的箭头是什么意思?其中一种选择是否比另一种更好?它们完全等效吗?
-
是的,有区别。好吧,让我把它作为答案,因为这对你有用。
标签: python regex parsing escaping