我想在任何现有的#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。
我们也欢迎为达到同样目的而提出的其他建议。
当前回答
相当全面的linuxtopia常见问题解答集合。它还强调了人们提供的一些答案不能与非gnu版本的sed一起工作,例如
sed '0,/RE/s//to_that/' file
在非gnu版本中必须是
sed -e '1s/RE/to_that/;t' -e '1,/RE/s//to_that/'
但是,这个版本不能与gnu sed一起工作。
下面是一个两者都适用的版本:
-e '/RE/{s//to_that/;:a' -e '$!N;$!ba' -e '}'
ex:
sed -e '/Apple/{s//Banana/;:a' -e '$!N;$!ba' -e '}' filename
其他回答
# sed script to change "foo" to "bar" only on the first occurrence
1{x;s/^/first/;x;}
1,/foo/{x;/first/s///;x;s/foo/bar/;}
#---end of script---
或者,如果你喜欢:编辑注:只适用于GNU sed。
sed '0,/foo/s//bar/' file
源
没什么新内容,只是可能有一些更具体的答案:sed -rn '0,/foo(bar)。* / % % \ 1% p '
示例:xwininfo -name unit -launcher输出如下:
xwininfo: Window id: 0x2200003 "unity-launcher"
Absolute upper-left X: -2980
Absolute upper-left Y: -198
Relative upper-left X: 0
Relative upper-left Y: 0
Width: 2880
Height: 98
Depth: 24
Visual: 0x21
Visual Class: TrueColor
Border width: 0
Class: InputOutput
Colormap: 0x20 (installed)
Bit Gravity State: ForgetGravity
Window Gravity State: NorthWestGravity
Backing Store State: NotUseful
Save Under State: no
Map State: IsViewable
Override Redirect State: no
Corners: +-2980+-198 -2980+-198 -2980-1900 +-2980-1900
-geometry 2880x98+-2980+-198
使用xwininfo -name unit -launcher|sed -rn '0提取窗口ID,/^xwininfo:窗口ID: (0x[0-9a- fa -f]+)。*/ s%%\1%p'产生:
0x2200003
你可以使用awk来做类似的事情。
awk '/#include/ && !done { print "#include \"newfile.h\""; done=1;}; 1;' file.c
解释:
/#include/ && !done
当行匹配“#include”并且我们还没有处理它时,在{}之间运行操作语句。
{print "#include \"newfile.h\""; done=1;}
这将打印#include "newfile.h",我们需要转义引号。然后我们将done变量设置为1,这样我们就不会添加更多的include。
1;
这意味着“打印出行”——一个空操作默认为打印$0,打印出整行。一个简单的程序,比sed更容易理解:-)
只需要在最后加上出现的次数:
sed s/#include/#include "newfile.h"\n#include/1
作为一种替代建议,您可能希望查看ed命令。
man 1 ed
teststr='
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
'
# for in-place file editing use "ed -s file" and replace ",p" with "w"
# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s <(echo "$teststr")
H
/# *include/i
#include "newfile.h"
.
,p
q
EOF