web-dev-qa-db-ja.com

IFステートメントを使用しているときにシェルコマンドを複数行に分割する方法を教えてください。

コマンドがifステートメントの一部である場合、シェル内でコマンドを複数の行に分割するにはどうすればよいですか。

これは動作します:

if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1                                                                       
fi

これはうまくいきません。

# does not work:
if ! fab --fabfile=.deploy/fabfile.py \ 
  --forward-agent \
  --disable-known-hosts deploy:$target; then   
  rc=1
fi

コマンド全体を実行する代わりに、次のようになります。

./script.sh: line 73: --forward-agent: command not found

さらに重要なことに、私がBashについて理解していないことから、将来的にこの問題や同様の問題を理解するのに役立つものが何が欠けているのでしょうか。

307

バックスラッシュの後から改行の前に空白(スペースまたはタブ文字)があると、行継続は失敗します。そのような空白がなければ、あなたの例は私のためにうまく働きます:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
   --forward-agent \
   --disable-known-hosts deploy:$target; then
     echo failed
else
     echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

コメントから推し進められた詳細がいくつかあります。シェルでの行継続バックスラッシュは、特別な場合ではありません。バックスラッシュが直後に続く文字を "引用符で囲む"ことは、通常の一般的な規則の一例です。この場合、次の文字は改行で、防止される特別な処理はコマンドを終了させることです。通常、引用符で囲まれた文字は文字通りコマンドに含まれています。バックスラッシュ改行は代わりに完全に削除されます。それ以外の点では、メカニズムは同じです。そしてバックスラッシュは直後に続く文字だけをクォートします。その文字がスペースまたはタブの場合、引用符で囲まれたスペースまたはタブが表示され、それ以降の改行は引用符で囲まれないままになります。

475
Mark Reed

Windows/WSL/Cygwinなどのユーザー向け:

あなたの行末が標準のUnixラインフィード、すなわち\n(LF)だけであることを確認してください。

Windowsの行末\r\n(CRLF)の行末を使用すると、コマンドラインの改行が中断されます。


これは、Windowsの行末で行末に\を付けると、\\r\nに変換されるためです。
Markが上記で正しく説明しているように、

バックスラッシュの後で改行の前に空白があると、行継続は失敗します。

これには、スペース()やタブ(\t)だけでなく、キャリッジリターン(\r)も含まれます。

43
Czechnology