我正在尝试搜索并替换linux机器上grep匹配的所有文件中的字符串。我有一些我想做的事情,但我不确定如何最好地将它们串在一起。
grep -n 'foo' *
会以下列形式提供输出:
[filename]:[line number]:[text]
对于grep返回的每个文件,我想用“bar”替换“foo”并将结果写回文件。有没有一个好方法呢?也许是一条奇特的管道?
答案 0 :(得分:108)
根据您提供的示例,这似乎是您想要的:
sed -i 's/foo/bar/g' *
它不是递归的(它不会下降到子目录中)。为了一个很好的解决方案替换整个树中的选定文件我会使用find:
find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
*.html
是文件必须匹配的表达式,.bak
复制原始文件后的-i
,扩展名为.bak(可以是任何扩展名)喜欢)和sed表达式末尾的g
告诉sed在一行(而不是只有第一行)上替换多个副本。要查找的-print
可以方便地显示哪些文件正在匹配。所有这些都取决于系统上这些工具的确切版本。
答案 1 :(得分:70)
您的意思是搜索并替换grep所匹配的所有文件中的字符串吗?
perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
修改强>
因为这似乎是一个相当受欢迎的问题,我认为我会更新。
现在我主要使用ack-grep
,因为它更加用户友好。所以上面的命令是:
perl -p -i -e 's/old/new/g' `ack -l searchpattern`
要处理文件名中的空格,您可以运行:
ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
您可以使用ack-grep
做更多事情。假设您只想将搜索限制为HTML文件:
ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
如果空白不是问题,那就更短了:
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
答案 2 :(得分:13)
如果您的sed(1)
有-i
选项,请按照以下方式使用:
for i in *; do
sed -i 's/foo/bar/' $i
done
如果没有,根据您要使用的语言,有以下几种方式可供选择:
ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *
perl -pi.bak -e 's/foo/bar/' *
答案 3 :(得分:6)
我喜欢并使用上述解决方案或系统范围的搜索,并在数千个文件中替换:
find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
我假设'* .htm?'而不是.html它搜索并找到.htm和.html文件。
我用更多系统使用的代字号(〜)替换.bak,以便更轻松地清理备份文件。
答案 4 :(得分:4)
这可以使用grep而无需使用perl或find。
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
答案 5 :(得分:3)
find . -type f -print0 | xargs -0 <sed/perl/ruby cmd>
将一次处理多个空格包含的文件名,每批加载一个解释器。快得多。
答案 6 :(得分:1)
已经给出了使用查找和 sed
的答案 find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
可能是标准答案。或者您可以使用perl -pi -e s/foo/bar/g'
代替sed
命令。
对于大多数快速用途,您可能会发现命令 rpl 更容易记住。这是替换(foo - &gt; bar),递归地对当前目录中的所有文件:
rpl -R foo bar .
默认情况下,它在大多数Linux发行版中都不可用,但可以快速安装(apt-get install rpl
或类似)。
然而,对于涉及正则表达式和反向替换,或文件重命名以及搜索和替换的更艰难的工作,我所知道的最通用和最强大的工具是 repren ,我写了一些小的Python脚本,用于一些棘手的重命名和重构任务。您可能更喜欢它的原因是:
答案 7 :(得分:1)
这实际上比看起来容易。
grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
容易腻。如果你很好地掌握了find,grep,xargs,sed和awk,那么在bash中对文本文件操作几乎没有什么是不可能的:)