Linux 如何grep和替换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15402770/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to grep and replace
提问by billtian
I need to recursively search for a specified string within all files and subdirectories within a directory and replace this string with another string.
我需要在目录内的所有文件和子目录中递归搜索指定的字符串,并将此字符串替换为另一个字符串。
I know that the command to find it might look like this:
我知道找到它的命令可能如下所示:
grep 'string_to_find' -r ./*
But how can I replace every instance of string_to_find
with another string?
但是如何string_to_find
用另一个字符串替换每个实例?
回答by minopret
Usually not with grep, but rather with sed -i 's/string_to_find/another_string/g'
or perl -i.bak -pe 's/string_to_find/another_string/g'
.
通常不使用 grep,而是使用sed -i 's/string_to_find/another_string/g'
or perl -i.bak -pe 's/string_to_find/another_string/g'
。
回答by billtian
I got the answer.
我得到了答案。
grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g'
回答by rezizter
Another option is to use find and then pass it through sed.
另一种选择是使用 find 然后通过 sed 传递它。
find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \;
回答by Marc Juchli
This works best for me on OS X:
这在 OS X 上最适合我:
grep -r -l 'searchtext' . | sort | uniq | xargs perl -e "s/matchtext/replacetext/" -pi
Source: http://www.praj.com.au/post/23691181208/grep-replace-text-string-in-files
来源:http: //www.praj.com.au/post/23691181208/grep-replace-text-string-in-files
回答by GuiltyDolphin
Another option would be to just use perl with globstar.
另一种选择是将 perl 与 globstar 一起使用。
Enabling shopt -s globstar
in your .bashrc
(or wherever) allows the **
glob pattern to match all sub-directories and files recursively.
shopt -s globstar
在您的.bashrc
(或任何地方)启用允许**
glob 模式递归地匹配所有子目录和文件。
Thus using perl -pXe 's/SEARCH/REPLACE/g' -i **
will recursively
replace SEARCH
with REPLACE
.
因此 usingperl -pXe 's/SEARCH/REPLACE/g' -i **
将递归替换SEARCH
为REPLACE
。
The -X
flag tells perl to "disable all warnings" - which means that
it won't complain about directories.
该-X
标志告诉 perl “禁用所有警告”——这意味着它不会抱怨目录。
The globstar also allows you to do things like sed -i 's/SEARCH/REPLACE/g' **/*.ext
if you wanted to replace SEARCH
with REPLACE
in all child files with the extension .ext
.
该globstar还允许你做这样的事情sed -i 's/SEARCH/REPLACE/g' **/*.ext
,如果你想更换SEARCH
同REPLACE
在扩展所有子文件.ext
。
回答by Dulith De Costa
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.
这将在与当前目录相关的所有文件中搜索字符串“ windows”,并在每个文件中每次出现字符串时将“ windows”替换为“ linux”。
回答by Walf
Other solutions mix regex syntaxes. To use perl/PCRE patterns for bothsearch and replace, and only process matching files, this works quite well:
其他解决方案混合了正则表达式语法。使用Perl / PCRE模式为两种搜索和替换,只有工艺匹配的文件,这个作品非常好:
grep -rlZPi 'match1' | xargs -0r perl -pi -e 's/match2/replace/gi;'
where match1
and match2
are usually identical but match1
may be simplified to remove more advanced features that are only relevant to the substitution, e.g. capturing groups.
wherematch1
和match2
通常是相同的,但match1
可以简化以删除仅与替换相关的更高级的功能,例如捕获组。
Translation: grep
recursively and list files that match this PCRE pattern, separated by nul to protect any special characters in the filename, then pipe those filenames to xargs
which is expecting a nul-separated list, but won't do anything if no names are received, and get perl
to substitute lines where matches are found.
翻译:grep
递归并列出与此 PCRE 模式匹配的文件,由 nul 分隔以保护文件名中的任何特殊字符,然后将那些需要xargs
以 nul 分隔的列表的文件名通过管道传输到其中,但如果没有收到名称,则不会执行任何操作,并perl
找到找到匹配项的替换行。
Add the I
switch to grep
to ignore binary files. For case-sensitive matching, drop the i
switch from grep
, and the i
flag attached to the substitution expression, but notthe i
switch on perl
itself.
添加I
开关以grep
忽略二进制文件。为区分大小写匹配,则删除i
从开关grep
,并且i
连接到替换表达式标志,但不是在i
上开关perl
本身。
回答by tsveti_iko
Be very careful when using find
and sed
in a git repo! If you don't exclude the binary files you can end up with this error:
在 git repo 中使用find
和使用时要非常小心sed
!如果不排除二进制文件,最终可能会出现此错误:
error: bad index file sha1 signature
fatal: index file corrupt
To solve this error you need to revert the sed
by replacing your new_string
with your old_string
. This will revert your replaced strings, so you will be back to the beginning of the problem.
要解决此错误,您需要sed
通过将您new_string
的old_string
. 这将恢复您替换的字符串,因此您将回到问题的开始。
The correct way to search for a string and replace it is to skip find
and use grep
instead in order to ignore the binary files:
搜索字符串并替换它的正确方法是跳过find
并使用grep
以忽略二进制文件:
sed -ri -e "s/old_string/new_string/g" $(grep -Elr --binary-files=without-match "old_string" "/files_dir")
Credits for @hobs
@hobs 的积分
回答by tinnick
Here is what I would do:
这是我会做的:
find /path/to/dir -type f -iname "*filename*" -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
this will look for all files containing filename
in the file's name under the /path/to/dir
, than for every file found, search for the line with searchstring
and replace old
with new
.
这将查找包含的所有文件filename
在文件的名义下/path/to/dir
,比中找到的每个文件,搜索与线searchstring
并更换old
有new
。
Though if you want to omit looking for a specific file with a filename
string in the file's name, than simply do:
但是,如果您想省略查找文件名中带有filename
字符串的特定文件,那么只需执行以下操作:
find /path/to/dir -type f -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
This will do the same thing above, but to all files found under /path/to/dir
.
这将做与上面相同的事情,但对/path/to/dir
.