簡體   English   中英

sed就地命令未從bash中的文件中刪除

[英]sed in-place command not deleting from file in bash

我有一個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中卻無法運行

這里:

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; # 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

任何時候在shell中編寫循環來操縱文本時,您都會使用錯誤的方法。 這可能更接近您真正應該做的事情(不需要環繞循環):

awk -v ks="${patternarr[@]}" 'BEGIN{gsub(/ /,")|(",ks); ks="("ks")} $0 !~ ks' file.txt

但是,如果您向我們展示一些示例輸入和預期輸出,則可能還有更好的方法(例如,僅檢查1個字段而不是整行,或使用單詞邊界或字符串比較或...。)

您需要使用雙引號在命令中插值shell變量,例如:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM