你们是我最后的依靠。
我有一个包含各种命令的 bashrc 文件。其中很多命令都是这个命令的变体
alias test='
test1 && test2
'
alias test1='
echo "i hope" && \
echo "this works"
'
alias test2='
echo "because" && \
echo "it annoys the hell out of me"
'
几天前,这个功能一直有效。从那时起,我就遇到了以下错误
$ test
i hope
this works
bash: syntax error near unexpected token `&&'
无论我使用&&
还是;
。命令 test1 和 test2 单独工作时均按预期运行,但我无法再将它们串联起来。我的 shell 是 bash,我让几位同事查看过它,但没人知道哪里出了问题。
$ echo $SHELL
/bin/bash
我是不是漏掉了什么?以前这些功能都管用,现在突然就不管用了,这很奇怪。
答案1
别名用文本替换文本。没有逻辑,只有文本替换。对于你的情况,请考虑使用 shell 函数。请参阅在 Bash 中,何时使用别名,何时使用脚本,何时编写函数?
Bash 扩展 后test
,会扩展test1
和test2
。这里没问题,这种多级扩展是允许的。但由于替换是纯文本的,因此所有字符都很重要。在一个定义中看似无害的字符可能会改变最终结果的逻辑,因为最终解释的是最终结果。
您的test
扩展为:
test1 && test2
然后扩展为:
echo "i hope" && \
echo "this works"
&& …
其中…
表示test2
扩展到什么(与问题无关)。只有这样才能解释结果。
后面的换行符"it works"
是 扩展后的最后一个字符test1
。它是未转义的,它终止前面的命令。&&
下一行中的 是意外的。
如果没有那个麻烦的换行符,情况就会有所不同:
alias test1='
echo "i hope" && \
echo "this works"'
或者如果它被转义了:
alias test1='
echo "i hope" && \
echo "this works"\
'
我相信我已经解释了这个问题并“解决”了它。不过我认为正确的做法是不要这样使用别名. 别名使用别名来构建一些逻辑应该被函数调用函数所取代。别名不是为了构建逻辑。
如果test1
和test2
是正常工作的 shell 函数(我的意思是每个函数都可以独立工作),那么表达式test1 && test2
将按预期工作,无论定义中的换行符如何test1
。这将起作用,因为表达式的逻辑将在执行test1
和(可选)之前确定。在别名和在 shell 尝试确定逻辑之前展开的test2
情况下(如我们所见),它们会影响逻辑。test1
test2
这不仅仅与换行符有关。执行以下示例:
alias foo='echo 1; echo 2'
false && foo
如果您不知道foo
是别名(或者您知道,但不知道别名的工作原理),那么您会期望foo
被false && foo
整体省略。 不,echo 2
将被执行。 这是因为最终命令是false && echo 1; echo 2
并且其逻辑与您预期的不同。
“等效” shell 函数表现更好。以下代码片段foo
根本不会执行,正如您所期望的那样false && foo
:
unalias foo
foo() { echo 1; echo 2; }
false && foo
对我来说,理解别名愚蠢地取代文字与文字是一个转折点。我所有与别名有关的麻烦都源于没有意识到这个基本事实。
另外要注意的test
是标准命令. 你不应该创建别名或名为的函数test
,除非你的目标是故意替换标准test
。