我想在任何现有的#include之前,用一个额外的include指令更新大量的c++源文件。对于这类任务,我通常使用带有sed的小型bash脚本来重写文件。
我如何得到sed替换一个文件中字符串的第一次出现,而不是替换每一次出现?
如果我用
sed s/#include/#include "newfile.h"\n#include/
它替换所有#includes。
我们也欢迎为达到同样目的而提出的其他建议。
我想在任何现有的#include之前,用一个额外的include指令更新大量的c++源文件。对于这类任务,我通常使用带有sed的小型bash脚本来重写文件。
我如何得到sed替换一个文件中字符串的第一次出现,而不是替换每一次出现?
如果我用
sed s/#include/#include "newfile.h"\n#include/
它替换所有#includes。
我们也欢迎为达到同样目的而提出的其他建议。
当前回答
我会用一个awk脚本来做到这一点:
BEGIN {i=0}
(i==0) && /#include/ {print "#include \"newfile.h\""; i=1}
{print $0}
END {}
然后用awk运行它:
awk -f awkscript headerfile.h > headerfilenew.h
可能有点草率,我是新手。
其他回答
#!/bin/sed -f
1,/^#include/ {
/^#include/i\
#include "newfile.h"
}
该脚本的工作原理:对于第1行和第一个#include(在第1行之后)之间的行,如果该行以#include开头,则在指定的行前面加上。
但是,如果第一个#include在第1行,那么第1行和下一个#include都将有该行前置。如果您正在使用GNU sed,它有一个扩展,其中0,/^#include/(而不是1,)将做正确的事情。
这可能为你工作(GNU sed):
sed -si '/#include/{s//& "newfile.h\n&/;:a;$!{n;ba}}' file1 file2 file....
或者如果内存不是问题:
sed -si ':a;$!{N;ba};s/#include/& "newfile.h\n&/' file1 file2 file...
使用GNU sed的-z选项,您可以像处理一行文件一样处理整个文件。这样,s/…/…/将只替换整个文件中的第一个匹配项。记住:s/…/…/只替换每行中的第一个匹配项,但是使用-z选项sed将整个文件视为一行。
sed -z 's/#include/#include "newfile.h"\n#include'
在一般情况下,您必须重写sed表达式,因为模式空间现在包含整个文件,而不仅仅是一行。一些例子:
s /文本。*//可以重写为s/text[^\n]*//。[^\n]匹配除换行符以外的所有内容。[^\n]*将匹配文本后的所有符号,直到出现换行符。 S /^text//可以重写为S /(^|\n)text//。 S /text$//可以重写为S /text(\n|$)//。
我将提出一个建议,这并不完全是最初的问题所要求的,但对于那些还想特别替换匹配的第二次出现,或任何其他特别枚举的正则表达式匹配的人来说。使用python脚本和for循环,如果需要从bash脚本调用它。这是它看起来像我,在我替换特定行包含字符串-项目:
def replace_models(file_path, pixel_model, obj_model):
# find your file --project matches
pattern = re.compile(r'--project.*')
new_file = ""
with open(file_path, 'r') as f:
match = 1
for line in f:
# Remove line ending before we do replacement
line = line.strip()
# replace first --project line match with pixel
if match == 1:
result = re.sub(pattern, "--project='" + pixel_model + "'", line)
# replace second --project line match with object
elif match == 2:
result = re.sub(pattern, "--project='" + obj_model + "'", line)
else:
result = line
# Check that a substitution was actually made
if result is not line:
# Add a backslash to the replaced line
result += " \\"
print("\nReplaced ", line, " with ", result)
# Increment number of matches found
match += 1
# Add the potentially modified line to our new file
new_file = new_file + result + "\n"
# close file / save output
f.close()
fout = open(file_path, "w")
fout.write(new_file)
fout.close()
用例可能是您的事件分布在整个文件中,但您知道您只关心前10、20或100行。
然后简单地处理这些行就可以解决问题——即使OP的措辞只是首先考虑。
sed '1,10s/#include/#include "newfile.h"\n#include/'