首页 > 解决方案 > Python:搜索和替换但忽略注释行

问题描述

我实际上想进行搜索和替换,但忽略我所有的注释行,我也只想替换第一个找到的...

输入文件.txt

#replace me
#replace me
replace me
replace me

...就像:

text = text.replace("replace me", "replaced!", 1) # with max. 1 rep.

但我不确定如何处理(忽略)这些评论。这样我得到:

#replace me
#replace me
replaced!
replace me

标签: python

解决方案


如我所见,现有解决方案存在以下几个问题中的一个或多个

  • 不完整(例如要求在行首匹配)
  • 不完整(例如要求匹配不包含\n
  • 笨重(例如 looong 基于文件的解决方案)

我很确定纯正则表达式解决方案需要可变宽度的lookbehinds,re模块不支持(尽管我认为regex模块支持)。不过,只要稍加调整,正则表达式仍然可以提供相当清晰的答案。

import re

i = re.search(r'^([^#\n]?)+replace me', string_to_replace, re.M).start()

replaced_string = ''.join([
    string_to_replace[:i],
    re.sub(r'replace me', 'replaced!', string_to_replace[i:], 1, re.M),
])

这个想法是您找到包含匹配开始的第一个未注释行,然后替换从该行开始'replace me'找到的第一个实例。正则表达式中的位说^([^#\n]?)+

  1. ^-- 找到一行的开始。
  2. ([^#\n]?)+([^#\n]?)--在匹配表达式的其余部分之前, 尽可能少地查找。
    • ([^#\n]?)- 查找 0 或 1 个[^#\n]
      • [^#\n]- 找到任何不是#或的东西\n

请注意r'',在创建正则表达式时,我们使用原始字符串来防止双重转义,例如反斜杠,并且我们re.M用于跨换行符进行搜索。

请注意,如果要替换的字符串包含 pattern ,则行为有点奇怪\n#。在这种情况下,您最终会替换部分或全部一个或多个注释行,这可能不是您想要的。考虑到替代方案的问题,我倾向于说替代方案都是错误的方法。

如果这不是您想要的,排除所有注释行会变得更加奇怪,因为它们如何重新合并在一起存在一些不确定性。例如,考虑以下输入文件。

#comment 1
replace
#comment 2
me
replace
me

如果要替换字符串会发生什么replace\nme\n#comment 2您是否因为夹在中间而排除了第一场比赛?如果你使用第一场比赛,\n#comment 2去哪里?它是在更换之前还是之后?更换多条线是否也可以夹在中间?你只是删除它吗?


推荐阅读