python - 在正则表达式中转义美元符号不起作用

标签 python regex

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

我需要浏览一些类似 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/

相关文章:

Python 正则表达式模块与 re 模块 - 模式不匹配

regex - Vim:编辑 python.vim 语法文件以像 Textmate 一样突出显示

Python:如何获取 GPU 数量

c# - 如何使用正则表达式从列表中提取字符串匹配项?

python - python问题中的排序列表

android - 当我翻转手机时,Kivy Android APK 崩溃

javascript - regexp 将 '1x' 和 '1x²' 替换为 'x' 和 'x²' (javascript)

java - 我们应该如何验证正则表达式语法

python - Django ORM 不同查询,其中顺序由带注释的字段完成,您需要不同的 ('id' )

python - 从每行的开头删除制表符和空格