我发现——可能是在 20 世纪 90 年代中期(!)——这个结构
export var=value
是 Bashism,可移植的表达是
var=value
export var
我多年来一直提倡这一点,但最近有人向我提出质疑,我真的找不到任何文件来支持我曾经坚定的信念。
谷歌搜索"export: command not found"
似乎没有提出任何有人确实遇到此问题的案例,所以即使它是真实的,我想这也不是很常见。
(我得到的点击似乎是新手复制/粘贴标点符号,最后得到'export: command not found
或类似的,或尝试export
与 一起使用sudo
;以及csh
尝试使用 Bourne shell 语法的新手用户。)
我可以肯定地说它可以在 OS X 和各种 Linux 发行版上运行,sh
包括dash
.
sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"' # see that it really is exported
value
在当今世界,可以安全地说export var=value
使用安全吗?
我想了解一下后果是什么。如果它不能移植到 v7“Bourne classic”,那就只不过是琐事而已。如果在生产系统中 shell 确实无法处理此语法,那么了解这一点将会很有用。
答案1
它不是 bashism,而是符合 POSIX 的语法。它实际上是很久以前作为 kshism 开始的,后来被几乎所有基于 Bourne 语法的 shell 采用。唯一臭名昭著的例外是/bin/sh
Solaris 10 及更早版本,它坚持旧版 Bourne shell 语法。希望 Solaris 11 使用符合 POSIX 标准的 shell 作为/bin/sh
.
顺便说一句,export
它已经是旧版 Bourne shell 中的内置命令,因此在谷歌上搜索export: command not found
会产生误导。
export
以下是与赋值结合使用时的旧版 Bourne shell 行为:
$ export var=22
var=22: is not an identifier
对于怀旧者来说,这个原始Bourne shell的源代码可用并且可以针对大多数 Unix 和 Linux 发行版进行编译。
答案2
export foo=bar
不受 Bourne shell(一种 70 年代的旧 shell,现代实现如 ash/bash/ksh/yash/zsh 均源于此)的支持sh
。这是由 引入的ksh
。
在 Bourne shell 中,您可以执行以下操作:
foo=bar export foo
或者:
foo=bar; export foo
或与set -k
:
export foo foo=bar
现在,行为:
export foo=bar
因外壳而异。
问题在于赋值和简单命令参数的解析和解释不同。
上面的内容foo=bar
被某些 shell 解释为命令参数,而被其他 shell 解释为赋值(有时)。
例如,
a='b c'
export d=$a
被解释为:
'export' 'd=b' 'c'
使用一些 shell(ash
,旧版本zsh
(在 sh 模拟中),yash
)和:
'export' 'd=b c'
在其他 ( bash
, ksh
) 中。
尽管
export \d=$a
或者
var=d
export $var=$a
在所有 shell 中都会被解释为相同的(如'export' 'd=b' 'c'
),因为反斜杠或美元符号会阻止那些支持它的 shell 将这些参数视为赋值。
如果export
它本身被引用或者是某些扩展的结果(即使是部分扩展),根据 shell,它也将停止接受特殊处理。
看局部变量赋值需要引号吗?了解更多详情。
Bourne 语法如下:
d=$a; export d
所有 shell 的解释都是相同的,没有歧义(d=$a export d
也适用于 Bourne shell 和 POSIX 兼容 shell,但不适用于最新版本,zsh
除非在sh
仿真中)。
情况可能会变得更糟。参见例如最近的讨论bash
当涉及到数组的时候。
(IMO,引入这一点是一个错误特征)。