Bash - 带变量的sed语法

时间:2016-01-25 01:55:11

标签: bash sed

我有两个包含字符串的变量VAR1和VAR2。我想要做的是浏览具有.txt扩展名的文件列表,并将VAR1的所有出现更改为VAR2。到目前为止,它看起来像这样:

for i in `find . -name "*.txt"`
do
 echo $i
 sed -i -E "s|\$VAR1|\$VAR2|g" $i
done

我认为除了sed系列之外的一切都运行良好。我认为这是一个语法问题,但我还没有弄清楚它是什么。任何帮助,将不胜感激 感谢

4 个答案:

答案 0 :(得分:2)

你不应该逃避你的$变量。还要确保使用小写-e并引用文件名,以防它有空格:

sed -ri -e "s|$VAR1|$VAR2|g" "$i"

答案 1 :(得分:1)

由于sed的“查找和替换”功能面向正则表达式而不是文字字符串,因此您可能希望考虑使用sed的替代方法,例如:使用awk如下:

 awk -v from="$VAR1" -v to="$VAR2" '
   function replace(a,b,s,  n) {
     n=index(s,a);
     if (n==0) {return s}
     return substr(s,1,n-1) b replace(a,b, substr(s,n+length(a)));
   }
   {print replace(from, to, $0)} '

以上内容可以轻松与本页其他地方提到的find ... | while read f ; do .... done模式结合使用。

GNU awk支持相当于sed的'-i'选项,但最好只是将awk的输出定向到一个临时文件,然后将其放到适当位置。

答案 2 :(得分:1)

你设法引用了来自shell的美元符号(如果你使用单引号而不是双引号则没有必要)但这并没有改变美元符号在正则表达式中也有意义的事实。将反斜杠加倍以从shell和sed中逃逸,或使用单引号使反斜杠进入sed。或者,使用不需要反斜杠的表示法。

sed -i -E 's|[$]VAR1|$VAR2|g' "$i"

顺便提一下,你的循环有很多问题。如果文件名中包含空格,则for循环将无法正常工作,并且您需要quote循环内的参数。要完全处理包含特殊字符的文件名,您需要改为使用find -exec

find . -name "*.txt" -exec sed -i -E 's|[$]VAR1|$VAR2|g' {} \;

如果您的find支持\+而不是\;,请务必使用它。

答案 3 :(得分:0)

(1)使用成语for i in $(find ....) ; do ...; done通常会按预期工作,但它不健全。模式明显更好:

find ... | while read i ; do ... ; done

(2)如果$ VAR1和/或$ VAR2包含在正则表达式中具有特殊意义的字符,则需要注意一些事项。例如,括号("("和")")具有特殊意义,因此如果VAR1包含这些,则使用-r选项(或在Mac上,-E)选项)可能是在寻找麻烦。

(3)如果VAR1不包含八个字符中的任何一个,sed -i -e "s|$VAR1|$VAR2|g"可能会发挥作用:^ $ * [] \ |。如果VAR2不包含" |"," \"或"&"。

(4)如果您想以编程方式准备字符串($ VAR1和$ VAR2)以用于sed,请参阅this SO page;它显示了如何使用sed来消除字符串!