在所有文件中使用grep和sed查找和replacestring

我正在得到一个

sed: -e expression #1, char 22: unterminated `s' command 

我的脚本有问题吗? “老string”也有特殊的字符

 #!bin/bash oldstring='<script>"[oldscript]"</script>' newstring='<script>"[newscript]"</script>' grep -rl $oldstring /path/to/folder | xargs sed -is/$oldstring/$newstring/g 

正如@Didier所说的,你可以把你的分隔符改成除了/之外的东西:

 grep -rl $oldstring /path/to/folder | xargs sed -is@$oldstring@$newstring@g 
 grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g" 

当GNU的人们把递归的文件搜索引入grep时,他们真的搞砸了。 grep是用于在文件中找到RE并打印匹配的行(g / re / p记住?)不用于查找文件。 有一个非常好的工具,FINDing文件的名字非常明显。 无论发生在UNIX的口头禅上,做一件事,做得好吗?

无论如何,下面是你如何使用传统的UNIX方法来做你想做的事情(未经测试):

 find /path/to/folder -type f -print | while IFS= read -r file do awk -v old="$oldstring" -v new="$newstring" ' BEGIN{ rlength = length(old) } rstart = index($0,old) { $0 = substr($0,rstart-1) new substr($0,rstart+rlength) } { print } ' "$file" > tmp && mv tmp "$file" done 

不是通过使用awk / index()代替sed和grep,而是避免需要转义所有可能出现在您的旧字符串或新字符串中的RE元字符,并且找出一个字符作为您的sed分隔符, t出现在你的旧字符串或新字符串中,而且你不需要运行grep,因为替换只会出现在包含你想要的字符串的文件中。 说了这么一点,如果你不想修改文件的时候文件的时间戳发生改变,那么只要在执行mv之前在tmp和原始文件上做一个diff或者在AWK。

警告:以上不适用于包含换行符的文件名。 如果你有这些,那么让我们知道,我们可以告诉你如何处理它们。

sed表达需要引用

 sed -i "s/$oldstring/$newstring/g" 
 grep -rl SOSTITUTETHIS . | xargs sed -Ei 's/(.*)SOSTITUTETHIS(.*)/\1WITHTHIS\2/g'