Linux命令行全局搜索和替换

Mic*_*fik 79 linux awk grep sed

我正在尝试搜索并替换linux机器上grep匹配的所有文件中的字符串.我有一些我想做的事情,但我不确定如何最好地将它们串在一起.

grep -n 'foo' * 会给我输出形式:

[filename]:[line number]:[text]
Run Code Online (Sandbox Code Playgroud)

对于grep返回的每个文件,我想用"bar"替换"foo"并将结果写回文件.有没有一个好方法呢?也许是一个奇特的管道?

Mat*_*ttJ 108

根据您给出的示例,这似乎是您想要的:

sed -i 's/foo/bar/g' *
Run Code Online (Sandbox Code Playgroud)

它不是递归的(它不会下降到子目录中).为了一个很好的解决方案替换整个树中的选定文件我会使用find:

find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Run Code Online (Sandbox Code Playgroud)

*.html是文件必须匹配的表达式,.bak-i创建原始文件的副本之后,带有.bak扩展名(可以是您喜欢的任何扩展名),并且gsed表达式的末尾告诉sed替换多个副本一行(而不仅仅是第一行).该-print发现是一个方便,显示了正在匹配的文件.所有这些都取决于系统上这些工具的确切版本.

  • @knocte -i告诉sed修改文件,否则它只是将修改后的版本打印到stdout.如果你不想创建.bak文件,只省略'.bak'部分,-i也可以独立工作. (4认同)
  • 在OSX上,你需要给`find`命令一个目录来开始,比如`find.-name'*.html'`或`find directoryname/-name'*'`. (2认同)

arm*_*ino 70

你的意思是搜索和替换grep匹配的所有文件中的字符串?

perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
Run Code Online (Sandbox Code Playgroud)

编辑

因为这似乎是一个相当受欢迎的问题,我认为我会更新.

现在我大多使用,ack-grep因为它更加用户友好.所以上面的命令是:

perl -p -i -e 's/old/new/g' `ack -l searchpattern`
Run Code Online (Sandbox Code Playgroud)

要处理文件名中的空格,您可以运行:

ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
Run Code Online (Sandbox Code Playgroud)

你可以做更多的事情ack-grep.假设您只想将搜索限制为HTML文件:

ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
Run Code Online (Sandbox Code Playgroud)

如果空白不是问题,那就更短了:

perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files
Run Code Online (Sandbox Code Playgroud)

  • 我认为这可能与包含空格的文件/文件夹有问题.`无法打开Untitled:尝试"Untitled Folder/file.txt"时没有这样的文件或目录,<>第5行. (3认同)

Kel*_*tia 13

如果你sed(1)有一个-i选项,那么使用它如下:

for i in *; do
  sed -i 's/foo/bar/' $i
done
Run Code Online (Sandbox Code Playgroud)

如果没有,根据您要使用的语言,有以下几种方式可供选择:

ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *
perl -pi.bak -e 's/foo/bar/' *
Run Code Online (Sandbox Code Playgroud)

  • `for in in*; do ...`是多余的,sed可以将文件列表作为参数. (2认同)
  • @Jens为什么不通过在上面添加你自己的例子来改进这个答案呢? (2认同)

小智 6

我喜欢并使用上述解决方案或系统范围的搜索并替换成千上万的文件:

find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Run Code Online (Sandbox Code Playgroud)

我假设'*.htm?' 而不是.html它搜索并找到.htm和.html文件.

我用更多系统使用的波形符号(〜)替换.bak,以便更轻松地清理备份文件.