在 shell 脚本中执行 "export VAR=value" 是否可移植?
Is it portable to do "export VAR=value" in shell scripts?
我看到很多片段都这样做:
SOME_LONG_VARIABLE_NAME=whatever_value
export SOME_LONG_VARIABLE_NAME
我想知道为什么人们不这样做:
export SOME_LONG_VARIABLE_NAME=whatever_value
我的问题:
- 是否需要符合 POSIX 的 shell 来支持
export VAR=value
语法?即,它是否便携?
- 如果是这样,为什么这种较短的语法不流行?
如前所述,POSIX requires 支持语法:
export name[=word]...
当然,非 POSIX shell 可能会在此语法上失败,但这超出了
这个问题的范围。上面的语法是可移植的。
"Is it portable" 与 "is it POSIX" 不是同一个问题。 export var=value
由 POSIX 指定,但如果您针对更广泛的所有(当前和遗留)Bourne-like shells.
群体,则它不可移植
我不知道目前是否有供应商销售的系统不允许这种语法。但同样,"systems currently being sold" 和 "systems currently running" 是不同的问题。我们需要一些 AIX、HP-UX、Solaris 等的实际用户来告诉我们...
出于以下任一原因,您可能会发现使用两步 "assign then export" 的脚本:
- 该脚本是很久以前写的,此后一直处于维护模式。合并语句将是纯粹的外观更改,这是不可取的。
- 该脚本实际上旨在 运行 在某些具有非 POSIX
/bin/sh
的遗留系统上
- 作者很久以前就学习了 shell 编程,只是按照习惯做事,知道旧方法(当不与 POSIX 相矛盾时)至少与 POSIX。这种人也可能会看到用
expr
做算术,可能会出现神秘的构造${1+"$@"}
。
- (最坏的情况)作者在看不懂的情况下抄袭了其他脚本的点点滴滴,而这一段来自于前一类的脚本
这不是答案,但我想提一下我刚刚发现的以下问题。
以下代码片段在 bash 中的行为与在破折号中的行为不同:
names="one two three"
export BOBO=$names
- 在 bash 中,变量 BOBO 将按预期包含 "one two three"。
- 在短划线中,变量 BOBO 将包含 "one"。换句话说:在 dash 中,"export" 就像一个系统命令(如
ls
、echo
、...),在变量扩展在命令看到它之前执行的意义上。破折号中的命令实际上是 export BOBO=one two three
.
(为了使破折号表现得像 bash,我们需要用引号代替 "$names"
。或者一开始就不要使用 export var=val syntax
。)
local var=$val
存在同样的问题(不在 POSIX 中):你需要将 $val
包装在如果您希望破折号按预期处理它,请加引号。
考虑到 /bin/sh
在流行系统中(如 Ubuntu)实际上是破折号,这是一个巨大的问题。 (不知为何我没听说过!)
编辑:
我看到 "Are quotes needed for local variable assignment?" 中讨论了这个问题。
我看到很多片段都这样做:
SOME_LONG_VARIABLE_NAME=whatever_value
export SOME_LONG_VARIABLE_NAME
我想知道为什么人们不这样做:
export SOME_LONG_VARIABLE_NAME=whatever_value
我的问题:
- 是否需要符合 POSIX 的 shell 来支持
export VAR=value
语法?即,它是否便携? - 如果是这样,为什么这种较短的语法不流行?
如前所述,POSIX requires 支持语法:
export name[=word]...
当然,非 POSIX shell 可能会在此语法上失败,但这超出了 这个问题的范围。上面的语法是可移植的。
"Is it portable" 与 "is it POSIX" 不是同一个问题。 export var=value
由 POSIX 指定,但如果您针对更广泛的所有(当前和遗留)Bourne-like shells.
我不知道目前是否有供应商销售的系统不允许这种语法。但同样,"systems currently being sold" 和 "systems currently running" 是不同的问题。我们需要一些 AIX、HP-UX、Solaris 等的实际用户来告诉我们...
出于以下任一原因,您可能会发现使用两步 "assign then export" 的脚本:
- 该脚本是很久以前写的,此后一直处于维护模式。合并语句将是纯粹的外观更改,这是不可取的。
- 该脚本实际上旨在 运行 在某些具有非 POSIX
/bin/sh
的遗留系统上
- 作者很久以前就学习了 shell 编程,只是按照习惯做事,知道旧方法(当不与 POSIX 相矛盾时)至少与 POSIX。这种人也可能会看到用
expr
做算术,可能会出现神秘的构造${1+"$@"}
。 - (最坏的情况)作者在看不懂的情况下抄袭了其他脚本的点点滴滴,而这一段来自于前一类的脚本
这不是答案,但我想提一下我刚刚发现的以下问题。
以下代码片段在 bash 中的行为与在破折号中的行为不同:
names="one two three"
export BOBO=$names
- 在 bash 中,变量 BOBO 将按预期包含 "one two three"。
- 在短划线中,变量 BOBO 将包含 "one"。换句话说:在 dash 中,"export" 就像一个系统命令(如
ls
、echo
、...),在变量扩展在命令看到它之前执行的意义上。破折号中的命令实际上是export BOBO=one two three
.
(为了使破折号表现得像 bash,我们需要用引号代替 "$names"
。或者一开始就不要使用 export var=val syntax
。)
local var=$val
存在同样的问题(不在 POSIX 中):你需要将 $val
包装在如果您希望破折号按预期处理它,请加引号。
考虑到 /bin/sh
在流行系统中(如 Ubuntu)实际上是破折号,这是一个巨大的问题。 (不知为何我没听说过!)
编辑:
我看到 "Are quotes needed for local variable assignment?" 中讨论了这个问题。