使用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(不一定与grep
或sed
但与这些常见的Unix命令)。
你可以直接使用find
和-exec
到sed
而不是先用grep
定位oldstr
。 这可能会有点低效,但这可能并不重要。 通过这种方式, sed
replace在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_Letter
replacefoo:/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操作将依次应用于数组的每个成员,而扩展则是结果列表。