IFステートメントを使用する場合、シェルコマンドを複数の行に分割するにはどうすればよいですか?


385

コマンドが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についての私の理解から何が欠けているのですか?


2
エラーは何ですか?$ if ! cp -n log/server1.log \ > .; then echo no copy; fiエラーなしで実行できます。改行の後に\
Miserable Variable

15
端末のバックスラッシュの後にスペースがあります\ か?彼らは見にくいです。もしそうなら、あなたはあなたのエディタが末尾のスペースを削除するか、それらをより見やすくすることができるかどうかを見たいかもしれません。
msw

10
はい、それはターミナルのバックスラッシュの後のスペースでした。完全に。ありがとうございました。
ドミトリーミンコフスキー2013

そして、はい、申し訳ありませんが、「エラー」(予期しない結果)を投稿する必要がありました!悪い!編集しています。
ドミトリーミンコフスキー2013

何を理解しましたか?質問の一部でもありません。
hakre 2014年

回答:


567

バックスラッシュの後および改行の前に空白(スペースまたはタブ文字)がある場合、行連結は失敗します。そのような空白がないと、あなたの例は私にとってうまくいきます:

$ 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

コメントからいくつかの詳細が示されました。シェルの行継続バックスラッシュは、実際には特別なケースではありません。これは、バックスラッシュが直後の文字を「引用」し、通常は受ける特別な扱いを防ぐという、一般的な規則の単なる例です。この場合、次の文字は改行であり、防止されている特別な扱いはコマンドの終了です。通常、引用符で囲まれた文字は、文字通りコマンドに含まれます。代わりに、バックスラッシュ付きの改行は完全に削除されます。それ以外は、メカニズムは同じです。また、バックスラッシュは直後の文字のみを引用します。その文字がスペースまたはタブである場合、引用符で囲まれたスペースまたはタブを取得するだけで、後続の改行は引用符で囲まれません。


5
マーク、あなたが知っている、私は空白があったに違いない。`s. For example, when adding one after the first `の後に空白を追加した場合にのみエラーを再現できます./soundops: line 73: --forward-agent: command not found。私の問題は、このエラーを理解できなかったことです。空白があるとそのエラーが発生するのはなぜですか?whitespace + \nは ``を否定し、コマンドを区切りますか?
ドミトリーミンコフスキー2013

84
改行の前のバックスラッシュは、改行がコマンドを終了しないようにします。しかし、「\ n」のような特別なエスケープシーケンスがバックスラッシュとnの間でのみ機能するのと同様に、backslash-newlineはバックスラッシュと改行の間でのみ機能します。
マークリード

19
はははすごい、もちろんそれは理にかなっています。そのようにそれを見たことがない。目を見張るほどシンプルですが、それはエスケープされた改行です。私は目に見えない文字が嫌いです。それらがすべて表示されていれば、私にはもっと理にかなっています。ありがとうございました!
ドミトリーミンコフスキー2013

7
ほとんどのエディターでは、これらの非表示の文字を表示できます。
lucasvc 2015年

1
バックスラッシュと改行は有効なコマンドラインから削除されますが、次の行の先頭の空白は保持されます。したがって、それが問題であるかどうかは、単一行コマンドのその時点で空白が問題になるかどうかに依存します。
マークリード

52

Windows / WSL / Cygwinなどのユーザーの場合:

行末が標準のUnix改行、つまり\n(LF)のみであることを確認してください。

Windowsの\r\n行末(CRLF)の行末を使用すると、コマンド行の区切りが解除されます。


これは\、Windowsの行末で行末にあると、に変換されるため \ \r \nです。
マークが上で正しく説明しているように:

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

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


1
これにより、Windowsでスクリプトを作成し、それをWindows bashで使用するときに作成される問題が修正されます(例:bash -c MyShellScript.sh MyShellScript.shがWindowsエディターで作成された場合)。おそらくNotepad ++を使用して、MyShellScript.shをUNIX形式で保存する必要があります。
BSalita 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.