为什么不在分配变量的同一行上导出变量?


44

From 上一个命令的最后一个参数是什么?

shellcheck告诉您不要在分配变量的同一行上导出变量。

我想知道为什么?

做了同样的建议适用于aliasdeclareexportlocalreadonly,和typeset




9
有问题的shellcheck规则为SC2155。shellcheck Wiki上有很好的文档。
phunehehe

3
另外,一些较旧的外壳不会export一起接受和分配。的传家宝Bourne Shell中,例如,输出一个“富= 2不是标识符”错误。
丹尼斯·威廉姆森

Answers:


54

问题是,在击每一个命令只有一个退出代码。当您export foo="$(false)"的退出代码false被简单地丢弃。如果您改为

foo="$(false)"
export foo

例如,通过errexit设置可以对失败的第一条命令进行操作。

像这样声明和分配字符串文字export foo='bar'当然不会遭受此问题的困扰。但是,更改是软件开发中唯一的常数,并且通过将它们分开来对将来的这种声明完全是好的内务处理。

除了您提到的特定于分配的命令外,单个分配中还包含多个命令,例如foo="$(false)$(true)"。请参阅pipefailman bash的另一个陷阱。

要记住的另一件事是,声明和赋值的顺序有时是相关的。例如,您需要分配变量之前声明变量。(不幸的是,在第一次分配变量之前不能声明变量。)local readonly


因此,如果要从文字中设置变量,并且没有要丢弃的退出代码,那么在一行上完成所有操作就没有错。
Monty Harder '18

1
就此shellcheck错误而言,不是。但是,由于现在删除的答案在它们之间占了一半,因此Bourne shell不支持的赋值语法export,因此,多年来,如果某人的解释者很可能是Bourne shell,人们就已经开始这样做。
JdeBP

@JdeBP,请注意foo=$(cmd) export foo,尽管具有相同的警告,但Bourne shell确实支持,cmd退出状态会丢失(但如果失败则不会导致shell退出set -e)。
斯特凡Chazelas

我的第一句话已经涵盖了这一点。
JdeBP '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.