我想在任何现有的#include之前,用一个额外的include指令更新大量的c++源文件。对于这类任务,我通常使用带有sed的小型bash脚本来重写文件。

我如何得到sed替换一个文件中字符串的第一次出现,而不是替换每一次出现?

如果我用

sed s/#include/#include "newfile.h"\n#include/

它替换所有#includes。

我们也欢迎为达到同样目的而提出的其他建议。


当前回答

 # 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脚本来做到这一点:

BEGIN {i=0}
(i==0) && /#include/ {print "#include \"newfile.h\""; i=1}
{print $0}    
END {}

然后用awk运行它:

awk -f awkscript headerfile.h > headerfilenew.h

可能有点草率,我是新手。

 # 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 

用例可能是您的事件分布在整个文件中,但您知道您只关心前10、20或100行。

然后简单地处理这些行就可以解决问题——即使OP的措辞只是首先考虑。

sed '1,10s/#include/#include "newfile.h"\n#include/'

只需要在最后加上出现的次数:

sed s/#include/#include "newfile.h"\n#include/1