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

时间:2013-01-16 19:38:04

标签: 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

话虽这么说,我(显然)开始遇到类似这样的问题:

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

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

([^\"]|\\\")+     # a group of anything but a quote or an escaped quote

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

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

感谢您的帮助。

修改

作为正则表达式的测试,我试图使用以下代码在缩小的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)

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

3 个答案:

答案 0 :(得分:6)

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

r'''(\"\"\"|\'\'\'|\"|\')((?<!\\)\\\1|.)*?\1'''

以下是:

  • (\"\"\"|\'\'\'|\"|\')匹配Python开头引用,因为这恰好是从用于解析Python的代码中获取的。您可能不需要所有这些报价类型。
  • ((?<!\\)\\\1|.)匹配:只有一个匹配的引用,它只被转义为ONCE或任何其他字符。因此,\\"仍将被识别为字符串的结尾。
  • *?非贪婪地匹配尽可能多的人。
  • \1只是收尾报价。

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

如果你想要正确,而不仅仅是大多数正确,你可能必须使用真正的解析器。请查看parsleypyparsingany of these tools

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

答案 1 :(得分:3)

也许使用两个负面的背后:

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)

产量

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

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

答案 2 :(得分:0)

使用python,正确的正则表达式匹配双引号字符串是:

pattern = r'“(\。| [^”])*“'

它描述了字符串的开头和结尾“。对于两个双引号内的每个字符,它可以是转义字符,也可以是任何字符”。

unutbu的ansever是错误的,因为对于有效的字符串“\\\\”,无法与该模式匹配。