313

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

我知道找到它的命令可能如下所示:

grep 'string_to_find' -r ./*

但是我怎样才能string_to_find用另一个字符串替换每个实例呢?

4

9 回答 9

282

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

find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \;
于 2013-03-14T06:53:32.400 回答
232

我得到了答案。

grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g'
于 2013-03-14T06:42:44.307 回答
64

You could even do it like this:

Example

grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'

This will search for the string 'windows' in all files relative to the current directory and replace 'windows' with 'linux' for each occurrence of the string in each file.

于 2016-02-01T15:37:11.990 回答
36

这在 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

于 2014-01-25T07:52:37.977 回答
6

通常不使用 grep,而是使用sed -i 's/string_to_find/another_string/g'or perl -i.bak -pe 's/string_to_find/another_string/g'

于 2013-03-14T06:42:32.117 回答
6

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

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

match1并且match2通常相同,但match2可以包含仅与替换相关的更高级功能,例如捕获组。

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

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

于 2016-11-03T06:22:14.740 回答
4

在 git repo 中使用find和使用时要非常小心!sed如果您不排除二进制文件,则可能会出现此错误:

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

要解决此错误,您需要sed通过将您的替换new_string为您的old_string. 这将还原您替换的字符串,因此您将回到问题的开头。

搜索字符串并替换它的正确方法是跳过findgrep改为使用以忽略二进制文件:

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

@hobs 的学分

于 2018-07-11T08:34:13.183 回答
1

这是我要做的:

find /path/to/dir -type f -iname "*filename*" -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'

这将查找包含filename在文件名中的所有文件/path/to/dir,而不是对于找到的每个文件,搜索带有的行searchstring并替换oldnew

尽管如果您想省略在文件名中查找带有filename字符串的特定文件,而不是简单地执行以下操作:

find /path/to/dir -type f -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'

这将执行与上述相同的操作,但对/path/to/dir.

于 2019-08-29T06:27:36.547 回答
-1

另一种选择是将 perl 与 globstar 一起使用。

shopt -s globstar在您的.bashrc(或任何地方)启用允许**glob 模式以递归方式匹配所有子目录和文件。

因此 usingperl -pXe 's/SEARCH/REPLACE/g' -i **将递归替换SEARCHREPLACE

-X标志告诉 perl “禁用所有警告”——这意味着它不会抱怨目录。

globstar 还允许您执行一些操作,例如sed -i 's/SEARCH/REPLACE/g' **/*.ext,如果您想在所有具有扩展名的子文件中SEARCH替换为.REPLACE.ext

于 2015-09-12T17:16:29.947 回答