次のコードがあります:
sed -i "/#alias/a alias ll='ls -laGh'" /etc/zshrc
sed -i "/#alias/a alias l='ls -l'" /etc/zshrc
ファイル /etc/zshrc には次の内容があります:
#alias
しかし、コードを実行すると次のエラーが発生します。
sed: 1: "/etc/zshrc": invalid command code z
何が起こるか分からない
次のようにすべきです:
#alias
alias ll='ls -laGh'
alias l='ls -l'
それは私には役に立ちません:
#alias
alias ll='ls -laGh' alias l='ls -l'
答え1
ここで問題が 2 つあります。1 つ目は、macOS バージョンの では、バックアップ ファイルに使用する拡張子を指定するためsed
の明示的な引数を-i
オプションに指定する必要があることです。バックアップが必要ない場合は、その後に空の引数を渡す必要があります ( sed -i '' ...
)。これそしてこれstackoverflowで。
2 番目の問題は、a
コマンドでは追加する文字列の前にエスケープされた改行が必要であり、その後に改行が必要であることです。[man
ページ] から:
[1addr]a\
text Write text to standard output immediately before each attempt to
read a line of input, whether by executing the ``N'' function or
by beginning a new cycle.
これら両方を考慮すると、必要なことが行われるはずです。
sed -i '' "/#alias/a\\
alias ll='ls -laGh'
" /etc/zshrc
コマンド文字列で明示的な改行を避けたい場合は、 を定義しnl=$'\n'
、明示的な改行の代わりに を使用します。一度で複数の行を追加したい場合は、ループを使用して、一度にすべての行を追加するコマンド${nl}
を作成するのが一般的です。sed
nl=$'\n'
sedcmd=""
for aliascmd in "alias ll='ls -laGh'" "alias l='ls -l'"; do
sedcmd+="a\\${nl}${aliascmd}${nl};"
done
sed -i '' "/#alias/ { ${sedcmd} }" /etc/zshrc
または、複数のコマンドを実行したい場合は、次のようにします。
nl=$'\n'
sed -i '' "/#alias/a\\${nl}alias ll='ls -laGh'${nl}" /etc/zshrc
sed -i '' "/#alias/a\\${nl}alias l='ls -l'${nl}" /etc/zshrc
この最後のオプションがまだ機能しない場合は、実行してset -x
からもう一度試してください。zsh を使用している場合は、次のようなものが表示されるはずです。
+zsh:10> sed -i '' $'/#alias/a\\nalias ll=\'ls -laGh\'\n' /etc/zshrc
+zsh:11> sed -i '' $'/#alias/a\\nalias l=\'ls -l\'\n' /etc/zshrc
(数字だけが+zsh:something
異なり、ターミナル cwd の更新に関する無関係な内容も多数含まれます。) これによってすべてが 1 行に収まる唯一の理由は、コマンドの末尾の改行がsed
欠落している場合であると考えられます。
+zsh:11> sed -i '' $'/#alias/a\\nalias l=\'ls -l\'\n' /etc/zshrc
^^
this bit here
ちなみに、set +x
デバッグ トレースをオフにするには を使用します。