我需要在目录中的所有文件和子目录中递归搜索指定的字符串,并将该字符串替换为另一个字符串。
我知道找到它的命令可能像这样:
grep 'string_to_find' -r ./*
但是,如何string_to_find
用另一个字符串替换每个的实例?
sed -i 's/.*substring.*/replace/'
sed -i 's/\(.*\)substring\(.*\)/\1replace\2/'
我需要在目录中的所有文件和子目录中递归搜索指定的字符串,并将该字符串替换为另一个字符串。
我知道找到它的命令可能像这样:
grep 'string_to_find' -r ./*
但是,如何string_to_find
用另一个字符串替换每个的实例?
sed -i 's/.*substring.*/replace/'
sed -i 's/\(.*\)substring\(.*\)/\1replace\2/'
Answers:
另一种选择是使用查找,然后将其传递给sed。
find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \;
-i
需要参数的正确扩展字符串。例如,find /path/to/files -type f -exec sed -i "" "s/oldstring/new string/g" {} \;
无论如何,提供空字符串仍然会创建备份文件,与手册中所述的不同……
-i ""
为OS X 添加了。
CRLF
为LF
。
我得到了答案。
grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g'
grep
然后一次sed
。使用find
方法更有效,但是您提到的此方法确实有效。
sed -i 's/str1/str2/g'
到sed -i "" 's/str1/str2/g'
这个工作。
grep
将浏览所有文件,sed
仅扫描与匹配的文件grep
。使用find
其他答案中的方法,find
首先列出所有文件,然后sed
扫描该目录中的所有文件。所以这种方法并不一定要慢,这取决于有多少场比赛有和之间的搜索速度的差异sed
,grep
和find
。
您甚至可以这样做:
例
grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
这将在相对于当前目录的所有文件中搜索字符串“ windows ”,并在每个文件中每次出现的字符串中将“ windows ” 替换为“ linux ”。
grep
仅当存在不应修改的文件时,此选项才有用。sed
在所有文件上运行将更新文件的修改日期,但如果没有匹配项,则使内容保持不变。
-i
我相信sed
每变化倒是文件的文件时,即使内容不变,sed
也将转换行结束我不使用sed
在Windows中一个Git回购,因为所有CRLF
的改变LF
。
这在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
sort -u
偶数部分?您希望在什么情况下grep -rl
产生两次相同的文件名?
其他解决方案混合了正则表达式语法。使用Perl / PCRE模式为两种搜索和替换,只有工艺匹配的文件,这个作品非常好:
grep -rlZPi 'match1' | xargs -0r perl -pi -e 's/match2/replace/gi;'
其中match1
和match2
通常相同,但match1
可以简化以删除仅与替换有关的更高级的功能,例如捕获组。
翻译:grep
递归地列出与该PCRE模式匹配的文件,并用nul分隔以保护文件名中的任何特殊字符,然后通过管道将那些xargs
期望以nul分隔的列表的文件名传递到文件名,但是如果没有收到名称,则不会执行任何操作,并perl
找到找到匹配项的替代行。
将I
开关添加到grep
以忽略二进制文件。为区分大小写匹配,则删除i
从开关grep
,并且i
连接到替换表达式标志,但不是在i
上开关perl
本身。
find
不会搜索文件内容,关键是只处理匹配的文件而无需编写Perl程序。
要非常小心使用时find
和sed
在混帐回购协议!如果不排除二进制文件,则可能会出现以下错误:
error: bad index file sha1 signature
fatal: index file corrupt
为了解决这个错误,你需要恢复的sed
更换你new_string
与你的old_string
。这将还原您替换的字符串,因此您将回到问题的开始。
搜索字符串并替换它的正确方法是跳过find
并改用它grep
来忽略二进制文件:
sed -ri -e "s/old_string/new_string/g" $(grep -Elr --binary-files=without-match "old_string" "/files_dir")
@hobs的积分
这是我会做的:
find /path/to/dir -type f -iname "*filename*" -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
这将查找filename
下方文件名中包含的所有文件/path/to/dir
,而不是找到的每个文件,搜索带有的行searchstring
并替换old
为new
。
尽管如果要忽略查找文件名中带有filename
字符串的特定文件,则可以简单地执行以下操作:
find /path/to/dir -type f -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
上面的操作相同,但是对下找到的所有文件都相同/path/to/dir
。
另一个选择是将perl与globstar一起使用。
启用shopt -s globstar
您的.bashrc
(或任意位置)允许**
全局模式以递归方式匹配所有子目录和文件。
因此,使用perl -pXe 's/SEARCH/REPLACE/g' -i **
将递归替换SEARCH
用REPLACE
。
该-X
标志告诉perl“禁用所有警告”-这意味着它不会抱怨目录。
该globstar还允许你做这样的事情sed -i 's/SEARCH/REPLACE/g' **/*.ext
,如果你想更换SEARCH
同REPLACE
在扩展所有子文件.ext
。
grep
和sed
。