在正则表达式中逃避美元符号不起作用

Ale*_*kov 3 python regex

在开始之前,我知道有比正则表达式更好的方法(比如标记化器),这不是问题所在.我已经坚持使用正则表达式,它已经按照我的需要工作,除了一个特殊情况,这是我需要的建议.

我需要扫描一些类似JavaScript的代码,并new在每个对象声明前插入关键字.我已经知道需要这个关键字的所有对象的名字了,我知道在我开始之前它们都不会在代码中有那个关键字(所以我不需要处理重复的new单词或猜测某些东西是否是一个对象或者不是.例如,典型的行可能如下所示:

foo = Bar()
Run Code Online (Sandbox Code Playgroud)

我已经知道这Bar是一个'类',并且需要'new'来进行对象声明.以下正则表达式可以解决问题:

for classname in allowed_classes:
    line = re.sub(r'^([^\'"]*(?:([\'"])[^\'"]*\2)*[^\'"]*)\b(%s\s*\()' % classname, r'\1new \3', line)
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力,甚至确保它不会触及classname它在一个字符串内(正则表达式的第一部分告诉它确保前面有偶数引号 - 它有点天真,因为它会破坏嵌套引号,但我不需要处理那种情况).问题是,类名也可以包含$在其中.因此,如果$Bar存在于allowed_classes中,则允许以下行:

foo = $Bar()
Run Code Online (Sandbox Code Playgroud)

由于美元符号,上述正则表达式将忽略它.我想逃避它会做的伎俩,但这个逻辑似乎对上面的行没有影响,即使$Bar是其中一个类:

for classname in allowed_classes:
    line = re.sub(r'^([^\'"]*(?:([\'"])[^\'"]*\2)*[^\'"]*)\b(%s\s*\()' % re.escape(classname), r'\1new \3', line)
Run Code Online (Sandbox Code Playgroud)

我也尝试过手工使用它,\但它也没有效果.有人可以解释为什么转换$\$不工作有什么能解决?

谢谢

And*_*ark 9

你当前的正则表达式不起作用的原因是\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)
Run Code Online (Sandbox Code Playgroud)

通过使用前瞻,您可以处理以下两种情况:

  • classname不是从一开始$,所以在尝试匹配之前我们想要一个单词边界classname,\b前瞻的内部处理这个
  • classname确实开始$,所以如果下一个字符是$我们要匹配的.我使用\B\$它只会匹配如果前面的字符$不是单词字符,但这可能是不必要的,因为我不能想到任何有效的JS代码,那将是这种情况