使用grep和sed查找并replacestring

我正在使用以下search目录recursionsearch特定的string,并将其replace为另一个:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' 

这工作正常。 唯一的问题是,如果string不存在,那么sed失败,因为它没有得到任何参数。 这对我来说是一个问题,因为我使用ANT自动运行它,并且由于sed失败,构build失败。

如果找不到string,是否有办法使其失效?

我感兴趣的是我可以使用的一行简单的解决scheme(不一定与grepsed但与这些常见的Unix命令)。

你可以直接使用find-execsed而不是先用grep定位oldstr 。 这可能会有点低效,但这可能并不重要。 通过这种方式, sedreplace在find列出的所有文件上执行,但是如果oldstr不存在,那么显然不会对它执行操作。

 find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \; 

你的解决scheme是好的。 只有这样才能尝试:

 files=$(grep -rl oldstr path) && echo $files | xargs sed.... 

所以只有当grep返回0时才执行xargs ,例如在某些文件中findstring。

标准xargs没有好办法做到这一点; 你最好使用find -exec作为别人的build议,或者把sed封装在一个脚本中,如果没有参数,它就什么也不做。 GNU xargs具有--no-run-if-empty选项,而BSD / OS X xargs具有-L选项,看起来应该是类似的。

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

 grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null 

收益率

 sed: couldn't edit /dev/null: not a regular file 

我正在做3个不同的连接到远程服务器

 touch deleteme grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' ./deleteme rm deleteme 

虽然这不太优雅,并需要2个更多的连接到服务器(也许有办法做到一条线),它也有效地工作

我认为如果没有使用-exec你可以简单地提供/dev/null作为至less一个参数,

 grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null 

我的用例是我想用foo:/Drive_Letterreplacefoo:/Drive_Letter foo:/bar/baz/xyz在我的情况下,我可以用下面的代码来完成。 我在相同的目录位置有大量的文件。

 find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g' 

希望有所帮助。

如果你要replace一个固定的string或某种模式,我还想添加bash内置模式stringreplacevariablesreplace构造。 我不是自己描述它,而是引用bash手册中的部分:

${parameter/pattern/string}

该模式被扩展为产生一个模式,就像path名扩展一样。 参数被扩展, 模式与其值最长的匹配被replace为string 。 如果模式/开始, 模式的所有匹配都被replace为string。 通常只有第一场比赛被取代。 如果模式#开始,则它必须在参数的扩展值的开头匹配。 如果模式%开始,则它必须在参数的扩展值的末尾匹配。 如果string为null,则删除pattern的匹配,并且可以省略/ following 模式 。 如果参数@* ,则replace操作依次应用于每个位置参数,扩展是结果列表。 如果参数是一个以@*下标的数组variables,那么replace操作将依次应用于数组的每个成员,而扩展则是结果列表。