我有一个bash脚本,它检查文件中的字符串模式并删除整个行i同一个文件,但不知何故它不删除该行,并且没有从命令提示符中删除任何错误.same命令从文件中删除。
#array has patterns
for k in "${patternarr[@]}
do
sed -i '/$k/d' file.txt
done
sed版本是> 4
当这个循环完成时,我希望从file.txt中删除所有与数组中的字符串模式匹配的行
当我从命令提示符运行sed -i '/pataern/d file.txt
然后它工作正常但不在bash中
提前致谢
答案 0 :(得分:2)
下面:
sed -i '/$k/d' file.txt
sed脚本是单引号,它可以防止shell变量扩展。它(可能)将与
一起使用sed -i "/$k/d" file.txt
我说"可能"因为它会做什么取决于$k
的内容,它只是被代入sed代码并被解释为这样。如果$k
包含斜杠,它将会中断。如果它来自一个不值得信任的源代码,那么你可以打开自己的代码注入(特别是使用GNU sed,可以执行shell命令)。
考虑k=^/ s/^/rm -Rf \//e; #
。
将shell变量替换为sed代码(或任何其他代码)通常是个坏主意。更好的方法是使用GNU awk:
awk -i inplace -v pattern="$k" '!($0 ~ pattern)' file.txt
或者只使用grep -v
和临时文件。
答案 1 :(得分:1)
首先,你在for语句中的${patternarr[@]}
周围有一个未公开的双引号。
然后你的问题是你在sed参数中使用单引号,使你的shell不评估引号内的$k
:
% declare -a patternarr=(foo bar fu foobar)
% for k in ${patternarr[@]}; do echo sed -i '/$k/d' file.txt; done
sed -i /$k/d file.txt
sed -i /$k/d file.txt
sed -i /$k/d file.txt
sed -i /$k/d file.txt
如果你用双引号替换它们,这里就是:
% for k in ${patternarr[@]}; do echo sed -i "/$k/d" file.txt; done
sed -i /foo/d file.txt
sed -i /bar/d file.txt
sed -i /fu/d file.txt
sed -i /foobar/d file.txt
答案 2 :(得分:1)
任何时候你在shell中编写循环只是为了操作文本你都有错误的方法。这可能更接近你真正应该做的事情(不需要周围的循环):
awk -v ks="${patternarr[@]}" 'BEGIN{gsub(/ /,")|(",ks); ks="("ks")} $0 !~ ks' file.txt
但是如果你向我们展示一些样本输入和预期输出,可能还有更好的方法(例如只检查1个字段而不是整行,或使用字边界,或字符串比较或....)。 p>
答案 3 :(得分:0)
您需要使用双引号在sed命令中插入shell变量,例如:
for k in ${patternarr[@]}; do
sed -i "/$k/d" file.txt
done