
ファイルから入力された行を削除するエイリアス関数を作成しようとしています:
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"
。
ただし、置換式にシェル変数を挿入すると、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
これにより、関数はフィルターとして機能し、缶に書いてある通りのことしかできないつまり、入力から行を削除し、入力がどこから来たのか、どこに行くのかは考慮しません。