sed就地命令不从bash中的文件中删除

sed就地命令不从bash中的文件中删除,bash,sed,Bash,Sed,我有一个bash脚本,它检查文件中的字符串模式,并删除同一文件中的整行,但不知何故它不会删除该行,也不会引发任何错误。来自命令提示符的相同命令会从文件中删除 #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脚本,它检查文件中的字符串模式,并删除同一文件中的整行,但不知何故它不会删除该行,也不会引发任何错误。来自命令提示符的相同命令会从文件中删除

#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中不能
提前感谢

您需要使用双引号在命令内插入shell变量,如:

for k in ${patternarr[@]}; do
    sed -i "/$k/d" file.txt
done

您需要使用双引号在命令内插入shell变量,如:

for k in ${patternarr[@]}; do
    sed -i "/$k/d" file.txt
done
在这里:

sed脚本被单独引用,这防止了shell变量的扩展。它(可能)会和你一起工作

sed -i "/$k/d" file.txt
我之所以说“可能”,是因为它将做什么取决于
$k
的内容,它只是被替换成sed代码并被解释为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
和一个临时文件。

此处:

sed脚本被单独引用,这防止了shell变量的扩展。它(可能)会和你一起工作

sed -i "/$k/d" file.txt
我之所以说“可能”,是因为它将做什么取决于
$k
的内容,它只是被替换成sed代码并被解释为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
和一个临时文件。

首先,在for语句中,${patternarr[@]}
周围有一个未关闭的双引号

那么您的问题是在参数中使用单引号,使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

首先,在for语句中,
${patternarr[@]}
周围有一个未关闭的双引号

那么您的问题是在参数中使用单引号,使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

每当您在shell中编写循环只是为了操纵文本时,您的方法都是错误的。这可能更接近您真正应该做的事情(不需要周围的循环):


但是,如果您向我们展示一些示例输入和预期输出,可能还有更好的方法(例如,只检查1个字段而不是整行,或者使用单词边界,或者字符串比较,或者……),只要您在shell中编写循环来处理文本,您就有错误的方法。这可能更接近您真正应该做的事情(不需要周围的循环):

但是,如果您向我们展示一些示例输入和预期输出,可能还有更好的方法(例如,仅检查1个字段而不是整行,或使用单词边界,或字符串比较,或……)。