
我正在嘗試創建一個別名函數來從文件中刪除輸入的行:
function remove_line(){
line_to_remove="'s/^"$1"$//g'"
sed -i $(line_to_remove) my_file
}
例如:
remove_line domain.com
應該從給定檔案中刪除該網域。
然而,似乎$
沒有正確解釋。我究竟做錯了什麼?
答案1
你的主要問題$(line_to_remove)
是命令替換,即用括號內的命令輸出的文字替換的表達式(line_to_remove
我希望這會給您一個“命令未找到”錯誤)。您可能想使用"$line_to_remove"
它。
但是,將 shell 變數注入到sed
替換表達式中並不理想,因為它對注入的字串設定了太多條件(它必須是有效的正規表示式並且不能包含/
等)
相反,我建議使用grep
並將結果寫入標準輸出或寫入臨時文件,在成功執行 後替換原始文件grep
,或者您可以讓sponge
(來自 GNU moreutils 包)覆蓋原始文件。
remove_lines () {
grep -v -Fx -e "$1" my_file | sponge my_file
}
此處使用的選項可grep
確保作為函數的第一個參數給出的行按原樣使用(而不是作為正則表達式),從頭到尾匹配行,並從輸入中刪除匹配的行。
沒有sponge
:
remove_lines () {
tmpfile=$(mktemp)
grep -v -Fx -e "$1" my_file >"$tmpfile" && mv "$tmpfile" my_file
rm -f "$tmpfile"
}
mv
僅當成功執行時才會執行,grep
如果rm -f
未成功執行則刪除臨時檔案。
就我個人而言,我可能會這樣寫函數:
remove_lines () {
grep -v -Fx -e "$1"
}
這允許用戶像這樣使用它:
remove_lines "my line" <my_file | sponge my_file
some-command | remove_lines "bumble bee" | other-command
這使得該函數充當過濾器只做罐頭上所說的,即,它從輸入中刪除行,並且不關心輸入來自何處或去向何處。