gpt4 book ai didi

python - 如何扫描允许转义字符的字符串文字?

转载 作者:太空宇宙 更新时间:2023-11-03 10:58:20 25 4
gpt4 key购买 nike

我想解析一个输入字符串并确定它是否包含用双引号 (") 括起来的字符序列。字符序列本身不允许包含更多的双引号,除非它们被反斜杠转义,如下所示:\"

为了让事情变得更复杂,反斜杠可以自己转义,像这样:\\。因此不会转义前面有两个(或任何偶数个)反斜杠 (\\") 的双引号。更糟糕的是,不允许使用单个非转义反斜杠(即后跟 "\)。

我正在尝试使用 Python 的 re 模块来解决这个问题。module documentation告诉我们有关管道运算符 A|B 的信息:

As the target string is scanned, REs separated by '|' are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the '|' operator is never greedy.

但是,这并没有像我预期的那样工作:

>>> import re
>>> re.match(r'"(\\[\\"]|[^"])*"', r'"a\"')
<_sre.SRE_Match object; span=(0, 4), match='"a\\"'>

此正则表达式的想法是首先检查转义字符(\\\"),只有在未找到时,才检查未找到的任何字符"(但它可以是单个 \)。这可以发生任意次数,并且必须用文字 " 字符包围。

我希望字符串 "a\" 根本不匹配,但显然匹配。我希望 \" 匹配 A 部分和 B 部分不被测试,但显然它是。

我真的不知道回溯在这种情况下是如何工作的,但有没有办法避免它?

我想如果我在一个单独的步骤中首先检查初始 " 字符(并将其从输入中删除),它会起作用。然后我可以使用以下正则表达式来获取字符串的内容:

>>> re.match(r'(\\[\\"]|[^"])*', r'a\"')
<_sre.SRE_Match object; span=(0, 3), match='a\\"'>

这将包括转义引号。由于不会留下结束引号,我会知道总体而言,给定的字符串不匹配。

我是否必须这样做,或者是否可以使用单个正则表达式解决此问题而不需要额外的手动检查?

在我的实际应用程序中," 封闭的字符串只是更大模式的一部分,因此我认为在单个正则表达式中一次完成所有操作会更简单。

我发现了类似的问题,但那些人不认为单个非转义反斜杠可以是字符串的一部分:regex to parse string with escaped characters , Parsing for escape characters with a regular expression .

最佳答案

当您使用 "(\\[\\"]|[^"])*" 时,您匹配 " 后跟 0+ 个 序列\ 后跟 \",或非 ",然后是“结束”"。请注意,当您的输入是 "a\" 时,\ 与第二个替代分支 [^"] 匹配(因为反斜杠是一个有效的非 ").

您需要从非"中排除\:

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

因此,我们匹配 ",然后匹配非 " 和非 \(使用 [^\\"] ) 或任何转义序列(使用 \\.),0 次或多次。

但是,这个正则表达式不够有效,因为有很多回溯正在进行(由交替和量词引起)。展开版本是:

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

参见 regex demo

最后的模式匹配:

  • " - 双引号
  • [^"\\]* - 除了 \"
  • 之外的零个或多个字符
  • (?:\\.[^"\\]*)* - 零个或多个序列
    • \\. - 反斜杠后跟任何字符,但换行符
    • [^"\\]* - 除了 \"
    • 之外的零个或多个字符
  • " - 双引号

关于python - 如何扫描允许转义字符的字符串文字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37378156/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com