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

时间:2012-07-19 14:59:52

标签: shell sed awk

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

sed -e '1,10 s/Copyright/*Copyright*/g' file

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

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

/*
* Copyright 1234 XXXNAME, XYZPlace 
*  text text text text ...........
* blah blah blah */

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

3 个答案:

答案 0 :(得分:9)

如果我理解正确,你想:

  • 在前10行中找到没有版权声明的文件,
  • 向这些文件添加版权声明。

此外,您想要:

  • 在前10行中找到带有版权声明的文件,
  • 将其通知更新为标准文字。

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

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

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

find . -type f -not -exec grep -q Copyright {} \; -exec sed -i'' '2i/* Copyright */' {} \;

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

这是如何运作的

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' {} \;

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

for file in *;do sed -ne '10,$ta;/Copyright/d;:a;p' "$file"; done

接下来,我们重新添加新内容。

for file in *;do sed -i'' '2i/* Copyright */' "$file"; done

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

find . -type f -exec sed -i'' '2i/* Copyright */' {} \;

最终更新

在此之后我不能再花这么多时间了。

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

<强>什么

第一个-exec搜索单词&#34;版权所有&#34;在文件的前10行中。就像上面发布的第一个例子一样。如果grep找到任何内容,则此条件返回true。

第二个-exec进行替换。它将整个文件读入sed的保持缓冲区。然后,当它到达文件末尾时,它(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

维护您现有的版权信息,但至少它解决了多行问题。

答案 1 :(得分:0)

编辑:如果您的文件名包含空格,则下面的命令将不起作用,请参阅第一条评论。

肯定只能用sed来完成,但我想到的第一件事就是对存在该行的文件进行替换,然后使用标题将其添加到其余文件中

之类的东西
for f in $(grep -lv 'Copyright' *); do sed -i '1i *Copyright*' $f; done

这适用于当前文件夹中的所有文件,如果需要递归,请使用-r选项grep

P.S。我建议删除-i sed选项以进行测试,并在您确定该命令正常工作时添加它。

答案 2 :(得分:0)

要在文件的第1行插入包含文本copyright的单行,只有它不存在,您可以这样做:

sed '1{ /copyright/!i\
copyright
}' input-file

要插入多行:

sed '1{ /copyright/!i\
copyright\
second line
}' input-file

使用r从文件中读取版权是很诱人的,但我无法弄清楚如何在第1行之前而不是在第1行之后插入它。例如:

sed '1{ /copyright/! { x; r copyright-file
G}}' input-file

似乎应该这样做,但版权文件中的文字从第2行开始。