我实际上想进行搜索和替换,但忽略我所有的注释行,我也只想替换找到的第一个...
input-file.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
答案 0 :(得分:1)
如我所见,现有解决方案存在以下一个或多个问题:
\n
)我敢肯定,纯正则表达式解决方案将需要可变宽度的lookbehind,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]?)+
位表示
^
-查找一行的开头。([^#\n]?)+
-在匹配表达式的其余部分之前,尽可能少地找到([^#\n]?)
。
([^#\n]?)
-在[^#\n]
中查找0或1。
[^#\n]
-查找不是#
或\n
之外的任何东西。 请注意,我们正在使用原始字符串r''
来防止在创建正则表达式时双重转义,例如反斜杠,并且我们正在使用re.M
进行跨行搜索休息。
注意,如果您要替换的字符串包含模式\n#
,则该行为有点奇怪。在这种情况下,您将不得不替换一个或多个注释行的部分或全部,而这可能不是您想要的。考虑到替代方案存在的问题,我倾向于说替代方案都是错误的方法。
如果这不是您想要的,那么由于不确定如何将它们合并在一起,因此将所有注释行排除在外会变得很奇怪。例如,考虑以下输入文件。
#comment 1
replace
#comment 2
me
replace
me
如果要替换字符串replace\nme
,会发生什么?您是否因为\n#comment 2
介于两者之间而排除了第一个匹配项?如果您使用第一个匹配项,\n#comment 2
会去哪里?它是在更换之前还是之后?更换的多条线是否也一样,以便仍可以夹在中间?你只是删除它吗?
答案 1 :(得分:0)
具有一个标志,用于标记您是否已完成替换。然后仅当该标志为true并且行不是注释时才替换:
not_yet_replaced = True
with open('input-file.txt') as f:
for l in f:
if not_yet_replaced and not l.startswith('#') and 'replace me' in l:
l = l.replace('replace me', 'replaced!')
not_yet_replaced = False
print(l)
答案 2 :(得分:0)
我不确定您是否设法将文本从文件中取出,因此您可以这样做
f = open("input-file.txt", "r")
text = f.read()
f.close()
然后我要做的方法是先将文本分成这样的行
lines = text.split("\n")
然后在每一行进行替换,并检查它是否不以“#”开头
for index, line in enumerate(lines):
if len(line) > 0 and line[0] != "#" and "replace me" in line:
lines[index] = line.replace("replace me", "replaced!")
break
然后将线缝在一起。
new_text = "\n".join(lines)
希望这会有所帮助:)
答案 3 :(得分:0)
您可以在第一次出现后使用break
,如下所示:
with open('input.txt', 'r') as f:
content = f.read().split('\n')
for i in range(len(content)):
if content[i] == 'replace me':
content[i] = 'replaced'
break
with open('input.txt', 'w') as f:
content = ('\n').join(content)
f.write(content)
输出:
(xenial)vash@localhost:~/python/stack_overflow$ cat input.txt #replace me #replace me replaced replace me
答案 4 :(得分:0)
如果输入文件不是很大,则可以将其作为行列表读入内存。然后遍历行并替换第一个匹配的行。然后将这些行写回到文件中:
with open('input-file.txt', 'r+') as f:
lines = f.readlines()
substr = 'replace me'
for i in range(len(lines)):
if lines[i].startswith('#'):
continue
if substr in lines[i]:
lines[i] = lines[i].replace(substr, 'replaced!', 1)
break
f.seek(0)
f.truncate()
f.writelines(lines)
答案 5 :(得分:0)
最简单的方法是使用多行正则表达式及其sub()方法,并将其计数为1:
import re
r = re.compile("^replace me$", re.M)
s = """
#replace me
#replace me
replace me
replace me
"""
r.sub("replaced!", s, 1)
给予
#replace me
#replace me
replaced!
replace me
在线演示here