[英]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[@]}
雙引號。
然后您的問題是,您在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
任何時候在shell中編寫循環來操縱文本時,您都會使用錯誤的方法。 這可能更接近您真正應該做的事情(不需要環繞循環):
awk -v ks="${patternarr[@]}" 'BEGIN{gsub(/ /,")|(",ks); ks="("ks")} $0 !~ ks' file.txt
但是,如果您向我們展示一些示例輸入和預期輸出,則可能還有更好的方法(例如,僅檢查1個字段而不是整行,或使用單詞邊界或字符串比較或...。)
您需要使用雙引號在sed命令中插值shell變量,例如:
for k in ${patternarr[@]}; do
sed -i "/$k/d" file.txt
done
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.