我有两个包含字符串的变量VAR1和VAR2。我想要做的是浏览具有.txt扩展名的文件列表,并将VAR1的所有出现更改为VAR2。到目前为止,它看起来像这样:
for i in `find . -name "*.txt"`
do
echo $i
sed -i -E "s|\$VAR1|\$VAR2|g" $i
done
我认为除了sed系列之外的一切都运行良好。我认为这是一个语法问题,但我还没有弄清楚它是什么。任何帮助,将不胜感激 感谢
答案 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来消除字符串!