35

我得到一个

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

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

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

5 回答 5

49

正如@Didier 所说,您可以将分隔符更改为/

grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
于 2013-04-10T12:30:24.827 回答
13
grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g"
于 2014-10-28T06:26:22.650 回答
6

当 GNU 人将递归文件搜索引入 grep 时,他们真的搞砸了。grep 用于在文件中查找 RE 并打印匹配行(g/re/p 还记得吗?)不是用于查找文件。有一个非常好的工具,用于查找文件的名称非常明显。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 或在 fgrep -q 之前抛出哦。

警告:以上不适用于包含换行符的文件名。如果您有这些,请告诉我们,我们可以向您展示如何处理它们。

于 2013-04-11T12:53:39.207 回答
4

sed表达式需要被引用

sed -i "s/$oldstring/$newstring/g"
于 2013-04-10T08:21:06.940 回答
-1
grep -rl SOSTITUTETHIS . | xargs sed -Ei 's/(.*)SOSTITUTETHIS(.*)/\1WITHTHIS\2/g'
于 2014-11-07T14:25:19.233 回答