471

当命令是if语句的一部分时,如何在 shell 中将命令拆分为多行?

这有效:

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 的理解中缺少什么可以帮助我在未来理解这个问题和类似问题?

4

2 回答 2

687

如果您在反斜杠之后和换行符之前有空格(空格或制表符¹),则行继续将失败。没有这样的空格,你的例子对我来说很好:

$ 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

从评论中提升了一些细节:shell中的换行反斜杠并不是真正的特殊情况;它只是一般规则的一个实例,反斜杠“引用”紧随其后的字符,防止它通常受到任何特殊处理。在这种情况下,下一个字符是换行符,并且被阻止的特殊处理是终止命令。通常,引用的字符最终会包含在命令中。相反,反斜杠换行符被完全删除。但除此之外,机制是相同的。最重要的是,反斜杠只引用紧随其后的字符;如果该字符是空格或制表符,您只会得到一个文字空格或制表符;反斜杠不会影响后续的换行符。

¹ 或回车,就此而言,正如捷克学指出的那样。POSIX shell 不能与 Windows 格式的文本文件兼容,甚至在 WSL 中也不能。或者 Cygwin,但至少他们的 Bash 端口添加了一个igncr选项,您可以set -o使其具有回车耐受性。

于 2013-09-03T19:22:45.270 回答
67

对于 Windows/WSL/Cygwin 等用户:

确保您的行尾是标准的 Unix 换行符,即\n仅 (LF)。

使用 Windows 换行符\r\n(CRLF) 换行符会打断命令行换行符。


这是因为\在带有 Windows 行尾的行尾转换为 \ \r \n.
正如马克在上面正确解释的那样:

如果在反斜杠之后和换行符之前有空格,则续行将失败。

这不仅包括空格 ( ) 或制表符 ( \t),还包括回车 ( \r)。

于 2015-11-02T18:52:43.770 回答