我需要在一个目录中的所有文件和子目录中递归地搜索指定的字符串,并用另一个字符串替换此字符串。

我知道查找它的命令可能是这样的:

grep 'string_to_find' -r ./*

但是如何用另一个字符串替换string_to_find的每个实例呢?


当前回答

其他解决方案混合使用正则表达式语法。要使用perl/PCRE模式进行搜索和替换,并且只处理匹配的文件,这工作得很好:

grep -rlIZPi 'match1' | xargs -0r perl -pi -e 's/match2/replace/gi;'

Match1和match2通常是相同的,但match2可以包含更高级的功能,这些功能只与替换相关,例如捕获组。

翻译:grep递归和列表匹配的文件名,每个由null分隔,以保护任何特殊字符;将任何文件名管道到xargs,该xargs需要一个空分隔的列表;如果接收到任何文件名,则将它们传递给perl以执行实际的替换。

对于区分大小写的匹配,从grep中删除i标志,从s///表达式中删除i模式修饰符,但不要从perl本身中删除i标志。要包含二进制文件,请从grep中删除I标志。

其他回答

另一种选择是使用find,然后通过sed传递它。

find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \;

这在OS X上最适合我:

grep -r -l 'searchtext' . | sort | uniq | xargs perl -e "s/matchtext/replacetext/" -pi

来源:http://www.praj.com.au/post/23691181208/grep-replace-text-string-in-files

我得到了答案。

grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g'

在git repo中使用find和sed时要非常小心!如果你不排除二进制文件,你会得到这样的错误:

error: bad index file sha1 signature 
fatal: index file corrupt

要解决这个错误,您需要通过用old_string替换new_string来恢复sed。这将恢复替换的字符串,因此您将回到问题的起点。

搜索字符串并替换它的正确方法是跳过find,而是使用grep来忽略二进制文件:

sed -ri -e "s/old_string/new_string/g" $(grep -Elr --binary-files=without-match "old_string" "/files_dir")

感谢@hobs

现代防锈工具可以用来做这项工作。 例如,在所有(非忽略)文件中替换“oldstring”和“oldstring”分别为“newstring”和“newstring”,你可以:

使用fd和sd

fd -tf -x sd 'old([Ss]tring)' 'new$1' {}

使用羽绒

ned -R -p 'old([Ss]tring)' -r 'new$1' .

使用ruplacer

ruplacer --go 'old([Ss]tring)' 'new$1' .

忽略了文件

要包含被忽略的(通过.gitignore)和隐藏的文件,你必须指定它:

fd使用-IH, 使用—忽略—隐藏用于ruplacer。