在我开始之前,我知道有比正则表达式更好的方法(比如分词器),这不是问题所在。我已经坚持使用正则表达式,并且它已经按照我的需要工作了,除了一种特殊情况,这是我需要的建议。
我需要浏览一些类似 JavaScript 的代码并在每个对象声明前插入 new
关键字。我已经知道所有需要这个关键字的对象的名称,而且我知道在我开始之前它们都不会在代码中有那个关键字(所以我不需要处理重复的 new
单词或猜测某物是否是对象。例如,典型的行可能如下所示:
foo = Bar()
我已经知道 Bar
是一个“类”并且需要“new”来声明对象。以下正则表达式可以解决问题:
for classname in allowed_classes:
line = re.sub(r'^([^\'"]*(?:([\'"])[^\'"]*\2)*[^\'"]*)\b(%s\s*\()' % classname, r'\1new \3', line)
它就像一个魅力,甚至确保不要触摸 classname
当它在字符串中时(正则表达式的第一部分告诉它确保预先有偶数个引号 -这有点天真,因为它会用嵌套引号中断,但我不需要处理这种情况)。问题是,类名中也可能有 $
。因此,如果 $Bar
存在于 allowed_classes 中,则也允许使用以下行:
foo = $Bar()
由于美元符号,上面的正则表达式将忽略它。我认为转义它可以解决问题,但即使 $Bar
是其中一个类,这种逻辑似乎对上面的行没有影响:
for classname in allowed_classes:
line = re.sub(r'^([^\'"]*(?:([\'"])[^\'"]*\2)*[^\'"]*)\b(%s\s*\()' % re.escape(classname), r'\1new \3', line)
我也尝试使用 \
手动转义它,但它也没有效果。有人可以解释为什么将 $
转换为 \$
不起作用吗?有什么办法可以解决这个问题?
谢谢
最佳答案
您当前的正则表达式不起作用的原因是您在类名之前有一个 \b
。 \b
将匹配单词边界,因此仅匹配单词字符和非单词字符。对于字符串 foo = Bar()
,\b
将匹配空格和 B
,但对于 foo = $ Bar()
,\b
不能匹配空格和$
,因为它们都是非单词字符。
要解决此问题,请将 \b
更改为 (?=\b|\B\$)
,这是生成的正则表达式:
for classname in allowed_classes:
line = re.sub(r'^([^\'"]*(?:([\'"])[^\'"]*\2)*[^\'"]*)(?=\b|\B\$)(%s\s*\()' % classname, r'\1new \3', line)
通过使用 lookahead ,您可以处理以下两种情况:
classname
不以$
开头,所以我们在尝试匹配classname
之前需要一个单词边界,\b
在前瞻内部处理这个classname
确实以$
开头,所以如果下一个字符是$
我们要匹配。我使用了\B\$
所以它只会匹配$
之前的字符不是单词字符,但这可能是不必要的,因为我想不出任何在这种情况下有效的 JS 代码
关于python - 在正则表达式中转义美元符号不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13675129/