使用python的re模块正确解析字符串文字

Tho*_*ood 4 python regex

我正在尝试为我用Python编写的javascript预处理器添加一些轻量级降价支持.

在大多数情况下它是有效的,但有时我使用的正则表达式有点奇怪,我认为它与原始字符串和转义序列有关.

正则表达式是: (?<!\\)\"[^\"]+\"

是的,我知道它只匹配以字符开头的"字符串.然而,这个项目出于好奇而不是任何事情,所以我现在可以忍受它.

要打破它:

(?<\\)\"    # The group should begin with a quotation mark that is not escaped
[^\"]+      # and match any number of at least one character that is not a quotation mark (this is the biggest problem, I know)
\"          # and end at the first quotation mark it finds
Run Code Online (Sandbox Code Playgroud)

话虽如此,我(显然)开始遇到这样的问题:

"This is a string with an \"escaped quote\" inside it"

我不太确定如何说"除了引号之外的所有内容,除非该标记被转义".我试过了:

([^\"]|\\\")+     # a group of anything but a quote or an escaped quote
Run Code Online (Sandbox Code Playgroud)

,但这会导致非常奇怪的结果.

我完全准备好听到我说这一切都错了.为简单起见,假设这个正则表达式总是以双引号(")开头和结尾,以避免在混合中添加另一个元素.我真的很想了解到目前为止的情况.

谢谢你的帮助.

编辑

作为正则表达式的测试,我试图使用以下代码在缩小的jQuery脚本中找到所有字符串文字(使用下面的unutbu模式):

STRLIT = r'''(?x)   # verbose mode
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    .*?        # non-greedy 1-or-more characters
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    ''' 
f = open("jquery.min.js","r")
jq = f.read()
f.close()
literals = re.findall(STRLIT,jq)
Run Code Online (Sandbox Code Playgroud)

以下答案几乎解决了所有问题.确实出现的是jquery自己的正则表达式,这是一个非常优秀的案例.该解决方案不再错误地将有效的javascript标识为markdown链接,这确实是目标.

Eev*_*vee 6

我想我第一次看到这个想法...... Jinja2的源代码?后来将其移植到Mako.

r'''(\"\"\"|\'\'\'|\"|\')((?<!\\)\\\1|.)*?\1'''
Run Code Online (Sandbox Code Playgroud)

具体如下:

  • (\"\"\"|\'\'\'|\"|\')匹配Python开头引用,因为这恰好来自解析Python的代码.您可能不需要所有这些报价类型.
  • ((?<!\\)\\\1|.)匹配:只有一个匹配的引用,它只被转义为ONCE或任何其他字符.所以\\"仍然会被认为是字符串的结尾.
  • *? 非贪婪地尽可能多地匹配.
  • 而且\1只是收尾报价.

唉,\\\"仍然会被错误地检测为字符串的结尾.(模板引擎只用它来检查是否有一个字符串,而不是将其解压.)这是一个问题的正则表达式非常非常不适合; 如果没有在Perl中做疯狂的事情,你可以将真正的代码嵌入到正则表达式中,我不确定即使使用PCRE也是如此.虽然我喜欢被证明是错的.:)杀手(?<!...)必须是恒定长度,但你想检查在结束报价之前是否有任何偶数个反斜杠.

如果你想要正确,而不仅仅是大多数正确,你可能必须使用真正的解析器.看看欧芹,pyparsing任何这些工具.

编辑:顺便说一下,没有必要检查开头的引号在它之前没有反斜杠.这不是JS(或Python)中字符串之外的有效语法.


unu*_*tbu 5

也许使用两个负面的看法:

import re

text = r'''"This is a string with an \"escaped quote\" inside it". While ""===r?+r:wt.test(r)?st.parseJSON(r)    :r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data" '''

for match in (re.findall(r'''(?x)   # verbose mode
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    .*?        # 1-or-more characters
    (?<!\\)    # not preceded by a backslash
    "          # a literal double-quote
    ''', text)):
    print(match)
Run Code Online (Sandbox Code Playgroud)

产量

"This is a string with an \"escaped quote\" inside it"
""
"data"
Run Code Online (Sandbox Code Playgroud)

中的问号.+?使模式非贪婪。非贪婪导致模式在遇到第一个未转义的双引号时匹配。