使用grep和sed查找并替换字符串

Mic*_*ael 68 unix linux shell grep sed

我使用以下内容递归搜索特定字符串的目录,并将其替换为另一个:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g'
Run Code Online (Sandbox Code Playgroud)

这没关系.唯一的问题是,如果字符串不存在则sed失败,因为它没有得到任何参数.这对我来说是一个问题,因为我使用ANT自动运行它,并且构建因sed失败而失败.

有没有办法在没有找到字符串的情况下使其防故障?

我对我可以使用的一行简单解决方案感兴趣(不一定用grep或者sed用这些常见的unix命令).

Mic*_*ski 70

您可以使用find-exec直接进入sed,而不是第一个定位oldstrgrep.效率可能稍低,但这可能并不重要.这样,sed替换将在列出的所有文件上执行find,但如果oldstr不存在,则显然不会对其进行操作.

find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \;
Run Code Online (Sandbox Code Playgroud)

  • 我的问题是:即使文件中没有编辑,每个文件的时间戳也会重置为"现在",好像它们都被"触摸"一样. (2认同)

jm6*_*666 9

你的解决方案没问题.只能以这种方式尝试:

files=$(grep -rl oldstr path) && echo $files | xargs sed....
Run Code Online (Sandbox Code Playgroud)

所以xargs只有当grep返回时才执行0,例如在某些文件中找到字符串时.

  • 这是一个很好的被低估的解决方案!这就是我需要在grep的文件输出列表上执行sed,并避免错误:"无法读取....没有这样的文件或目录".感谢您的回答! (2认同)
  • 同意@Leopoldo.这看起来像Posixy和便携式(对于像Solaris这样的操作系统)和副作用最小的(没有触及每个文件mtime等).`files = $(grep -rl oldstr path | cut -f 1 -d':'| sort | uniq)`应该构建一个较小的列表,列出文件一次. (2认同)

gee*_*aur 7

标准xargs没有好办法; 你最好不要find -exec像其他人建议的那样使用,或者sed在没有参数的情况下将其包装在一个什么也不做的脚本中.GNU xargs--no-run-if-empty选项,BSD/OS X xargs有一个-L看起来应该做类似的选项.


Mic*_*ael 7

我采取了弗拉德的想法,并改变了一点点.代替

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null
Run Code Online (Sandbox Code Playgroud)

哪个收益率

sed: couldn't edit /dev/null: not a regular file
Run Code Online (Sandbox Code Playgroud)

我正在与远程服务器建立3个不同的连接

touch deleteme
grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' ./deleteme
rm deleteme
Run Code Online (Sandbox Code Playgroud)

虽然这不太优雅,并且需要2个与服务器的连接(也许有一种方法可以在一条线上完成),它也可以有效地完成工作