【问题标题】:How can I split a shell command over multiple lines when using an IF statement?使用 IF 语句时,如何将 shell 命令拆分为多行?
【发布时间】:2013-09-07 03:02:14
【问题描述】:

当命令是 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 的理解中缺少什么可以帮助我理解这个问题以及将来的类似问题?

【问题讨论】:

  • 错误是什么?我能够正确执行$ if ! cp -n log/server1.log \ > .; then echo no copy; fi,在\ 之后使用换行符
  • 终端反斜杠\ 后面有空格吗?他们很难看到。如果你这样做了,你可能想看看你是否可以让你的编辑器要么删除尾随空格,要么让它们更明显。
  • 是的,它是终端反斜杠后的空格。完全。谢谢。
  • 是的,对不起,我应该发布“错误”(意外结果)!我的错!立即编辑。
  • 你的理解是什么?这也不是问题的一部分。

标签: syntax sh


【解决方案1】:

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

$ 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

来自 cmets 的一些细节:shell 中的续行反斜杠并不是一个特殊情况;它只是一般规则的一个实例,反斜杠“引用”紧随其后的字符,防止它通常受到任何特殊处理。在这种情况下,下一个字符是换行符,并且被阻止的特殊处理是终止命令。通常,引用的字符最终会包含在命令中。相反,反斜杠换行符被完全删除。但除此之外,机制是相同的。最重要的是,反斜杠只引用紧随其后的字符;如果该字符是空格或制表符,您只会得到一个文字空格或制表符(这将是它自己的单独参数,因为反斜杠会阻止空格折叠到分隔其他参数的周围未加引号的空格中);反斜杠对后面的换行没有影响。

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

【讨论】:

  • 马克,你知道,我一定有空格。只有在`s. For example, when adding one after the first `之后添加空格时,我才能重现该错误,我得到./soundops: line 73: --forward-agent: command not found。我的问题是我不理解这个错误。为什么有空格会导致该错误?空格+\n“否定” `` 并分隔命令?
  • 换行符前面的反斜杠可防止换行符终止命令。但是就像“\n”这样的特殊转义序列只能在反斜杠和 n 之间没有任何内容时起作用,反斜杠换行符也只能在反斜杠和换行符之间没有任何内容时起作用。
  • 哈哈哈哇,当然有道理。从来没有这样看。令人大开眼界,但又如此简单:它只是一个转义的换行符。我讨厌看不见的角色。如果它们都是可见的,它们对我来说会更有意义。谢谢!
  • 在大多数编辑器中,您可以使那些不可见的字符可见。
  • 从有效命令行中删除反斜杠和换行符,但保留下一行的任何前导空格。所以这是否是一个问题取决于在单行命令中的那个时候空格是否是一个问题。
【解决方案2】:

对于 Windows/WSL/Cygwin 等用户:

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

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


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

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

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

【讨论】:

  • 这修复了在 Windows 中创建脚本然后在 Windows bash 中使用它时产生的问题(例如 bash -c MyShellScript.sh,其中 MyShellScript.sh 是在 Windows 编辑器中创建的)。您必须使用 notepad++ 以 UNIX 格式保存 MyShellScript.sh。
  • ^ 对于那些使用notepad++的人,在底部你可以看到文件的行尾是什么。如果它读取 Windows (CL CR),那么您应该将其更改为 Unix (LF)。你可以点击它来改变它。
  • 非常感谢!即使在 2020 年,您的回答也会有很大帮助!
猜你喜欢
  • 2022-12-16
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 2016-05-20
  • 2021-08-18
  • 1970-01-01
  • 2021-12-31
  • 2016-10-04
相关资源
最近更新 更多