用于搜索和替换/插入文件中的文本的Sed/Awk

SKR*_*SKR 3 shell awk sed

我正在尝试更新或插入一些注释,如版权标题到目录中的所有源文件(Linux).我的文件不一致,因此其中一些文件已经有标题,而其他文件根本没有标题.我试着sed查看前几行并替换.替换我的意思是更改已经具有最新版权标题的文件.

sed -e '1,10 s/Copyright/*Copyright*/g' file
Run Code Online (Sandbox Code Playgroud)

但是,如果找不到模式,则不会插入.我怎样才能做到这一点?

示例我在评论中提供或我试图实际替换/插入的是多行典型版权标题,如下所示

/*
* Copyright 1234 XXXNAME, XYZPlace 
*  text text text text ...........
* blah blah blah */
Run Code Online (Sandbox Code Playgroud)

它也可能包含一些特殊字符.

gho*_*oti 9

如果我理解正确,你想:

  • 在前10行中查找没有版权声明的文件,和
  • 为这些文件添加版权声明.

另外,你想要:

  • 在前10行中查找带有版权声明的文件,和
  • 将其通知更新为标准文本.

在我看来,这两个任务可以归结为一组:

  • 删除前10行中的所有现有版权声明
  • 在文件中插入新的版权声明.

如果我们可以安全地假设您在问题评论中放置的缩小版本的样本文本是有效的,并且应该插入到每个文件的第2行,那么以下内容应该实现第一组要求你正在使用GNU sed:

find . -type f -not -exec grep -q Copyright {} \; -exec sed -i'' '2i/* Copyright */' {} \;
Run Code Online (Sandbox Code Playgroud)

如果你没有运行GNU sed(即你在FreeBSD或OSX或Solaris等),请告诉我们,因为sed脚本会有所不同.

这是如何工作的

find命令获得以下选项:

  • -type f 告诉它只查看文件(不是目录或设备).
  • -not 反转以下选项.
  • -exec grep -q Copyright {} \;将搜索限制为包含版权的任何内容(修改者-not)
  • -exec sed -i'' '2i/* Copyright */' {} \; 插入您的版权声明.

如果您希望您的版权声明包含可由sed脚本解释的特殊字符,则此解决方案可能会遇到困难.但它回答了你的问题.:)

相反,如果我们想要处理修订后的要求,即首先删除现有的版权声明,那么我们可以用两个单行来完成:

首先,我们删除现有的版权声明.

find . -type f -exec sh -c 'head {} | grep -q Copyright' \; -exec sed -ne '10,$ta;/Copyright/d;:a;p' {} \;
Run Code Online (Sandbox Code Playgroud)

这可能有点多余,除非您想以递归方式遍历子目录,find默认情况下这样做.sed脚本对前10行中没有版权信息的文件不执行任何操作,因此如果所有文件都在一个目录中,则以下内容也应该起作用:

for file in *;do sed -ne '10,$ta;/Copyright/d;:a;p' "$file"; done
Run Code Online (Sandbox Code Playgroud)

接下来,我们重新添加新的.

for file in *;do sed -i'' '2i/* Copyright */' "$file"; done
Run Code Online (Sandbox Code Playgroud)

或者,如果您想通过子目录递归执行此操作:

find . -type f -exec sed -i'' '2i/* Copyright */' {} \;
Run Code Online (Sandbox Code Playgroud)

最终更新:

在此之后,我不能在这个上花更多的时间.

find . -type f \
  -exec sh -c 'head {} | grep -q Copyright' \; \
  -exec sed -ne '1h;1!H;${;g;s:/\*.*Copyright.*\*/:/* Copyright 1998-2012 */' {} \;
Run Code Online (Sandbox Code Playgroud)

什么

第一个-exec在文件的前10行中搜索"Copyright"一词.就像上面发布的第一个例子一样.如果grep找到任何内容,则此条件返回true.

第二个-exec是替代.它将整个文件读入sed的保持缓冲区.然后,当它到达文件的末尾时,it(g)会考虑保持缓冲区,而(s)会进行多行替换.

请注意,这可能需要进行一些调整,如果您在文件中的其他位置有注释,它可能根本不起作用.我不记得GNU sed是否支持非贪婪的明星.你可以自己研究一下.

这是我的测试:

$ printf 'one\n/* Copyright blah blah\n *\n */\ntwo\n' | sed -n '1h;1!H;${;g;s:/\*.*Copyright.*\*/:/* Copyright 1998-2012 */:g;p;}'
one
/* Copyright 1998-2012 */
two
Run Code Online (Sandbox Code Playgroud)

不会保留您现有的版权信息,但至少它可以解决多线问题.