grep -n 'foo' *
会以以下形式给出输出:[filename]:[line number]:[text]
对于grep返回的每个文件,我想通过将foo
替换为bar
来修改文件。sed -i 's/foo/bar/g' *
它不是递归的(不会进入子目录)。要在整个目录树中替换选定文件的好方法是使用find:
find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
*.html
是文件名必须匹配的表达式,-i
后面的.bak
将原文件复制并重命名为.bak(你可以使用任何扩展名),g
指示sed替换一行上的多个实例而不仅仅是第一个实例。-print
用于方便显示匹配的文件。所有这些都取决于系统中这些工具的确切版本。
你的意思是在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
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/' *
for i in *; do ...
是多余的,sed 可以接受文件列表作为参数。 - Jensfor i in *; do; sed -i 's/foo/bar/g' "$i"; done
- cat我喜欢并使用上述解决方案,或在数千个文件中进行系统范围的搜索和替换:
find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
我认为使用“*.htm?”而不是.html可以同时搜索并找到.htm和.html文件。
我将.bak替换为更广泛使用的波浪号(~),以便更轻松地清理备份文件。
这可以使用grep而不需要使用perl或find来完成。
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
xargs
手册(在 Ubuntu 上)说 -i
已经被弃用,应该使用 -I
。因此,我们应该这样写:grep -rli 'old-word' * | xargs -I filepath sed -i 's/old-word/new-word/g' filepath
。 - Max Wallacefind . -type f -print0 | xargs -0 <sed/perl/ruby cmd>
可以一次性处理包含多个空格的文件名,每批加载一个解释器,速度更快。
find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
。这可能是标准答案。或者,您可以使用perl -pi -e s/foo/bar/g'
代替sed
命令。rpl -R foo bar .
。它在大多数Linux发行版上默认不可用,但安装很快(apt-get install rpl
或类似命令)。查看 README 以获取示例。
不要解释。
grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
易如反掌。如果您对find,grep,xargs,sed和awk有很好的掌握,那么在bash中进行文本文件操作几乎是不可能的 :)
2022年的答案。
https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#how-can-i-search-and-replace-with-ripgrep
rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'
将ripgep找到foo模式的文件中所有'foo'实例替换为'bar'。sed的-i标志表示您正在就地编辑文件,s/foo/bar/g表示您正在执行将模式foo替换为bar的替换操作,并且您正在全局执行此替换操作(每个文件中的所有模式出现)。
find
命令提供一个起始目录,例如find . -name '*.html'
或find directoryname/ -name '*'
。 - Michiel Kauw-A-Tjoesed -ie 's/foo/bar/g' *
。 - vish