4

我正在尝试为我用 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

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

我已经做好充分准备听到我将这一切都错了。为简单起见,假设此正则表达式将始终以双引号 ( ") 开头和结尾,以避免在混合中添加另一个元素。我真的很想了解我到目前为止所拥有的。

感谢您的任何帮助。

编辑

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

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 错误识别为降价链接,这才是真正的目标。

4

3 回答 3

6

我想我第一次看到这个想法是在... Jinja2 的源代码?后来移植到Mako身上。

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

执行以下操作:

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

唉,\\\"仍然会被错误地检测为字符串的结尾。(模板引擎只使用它来检查是否有字符串,而不是提取它。)这是一个非常不适合正则表达式的问题;没有在 Perl 中做一些疯狂的事情,你可以在正则表达式中嵌入真正的代码,我不确定即使使用 PCRE 也是可能的。虽然我很想被证明是错误的。:) 杀手锏(?<!...)必须是constant-length,但您要检查在结束引号之前是否有偶数个反斜杠。

如果你想得到这个正确的,而不仅仅是大部分正确的,你可能必须使用一个真正的解析器。看看parsleypyparsing任何这些工具

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

于 2013-01-16T20:08:56.990 回答
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)

产量

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

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

于 2013-01-16T19:46:29.277 回答
0

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

模式 = r'"(\.|[^"])*"'

它描述了以 " 开头和结尾的字符串。对于两个双引号内的每个字符,它要么是转义字符,要么是任何字符期望 "。

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

于 2016-06-21T03:58:50.660 回答