在我的回答在这里,我使用了以下结构:
n=$1 shift
阅读令牌识别规范,我知道 shell 会将该行解析为两部分 - 变量赋值n=$1
和内置命令shift
。
但对我的答案的评论状态n=$1 shift
在某些 shell 中确实失败。
我进行了快速检查:
$ for shell in /bin/*[^c]sh; do
printf '=%-17s=\n' "$shell"
"$shell" -c 'a=$1 shift; echo "$a"' "$shell" 1
done
=/bin/ash =
1
=/bin/bash =
=/bin/dash =
1
=/bin/heirloom-sh =
1
=/bin/ksh =
1
=/bin/lksh =
1
=/bin/mksh =
1
=/bin/pdksh =
1
=/bin/posh =
1
=/bin/schily-osh =
1
=/bin/schily-sh =
1
=/bin/yash =
1
=/bin/zsh =
bash
除了和 之外,所有 shell 都zsh
可以工作。但bash
在posix
模式和仿真zsh
中sh
也确实有效:
$ ARGV0=sh bash -c 'a=$1 shift; echo "$a"' sh 1
1
$ ARGV0=sh zsh -c 'a=$1 shift; echo "$a"' sh 1
1
var=value; shift
在所有 shell 中都可以使用。
那么,这些结构在 POSIX 兼容的 shell 中是否相同?
答案1
在 Bourne Shell 中,任何类型的内置命令之前的变量赋值都会影响整个 shell。
由于 David Korn 在添加历史编辑之前就开始创建带有许多内置函数的增强型 Bourne Shell,因此对他来说,这种行为显然是一个问题。
因此,ksh88 的行为有所不同,并且这种行为已成为较新的 POSIX 标准的主宰。
目前的规则是:
VAR=value
在 aspecial builtin
影响整个 shell之前VAR=value
即使这是内置命令,任何其他命令也只会影响此命令。
您的错误是使用special builtin
.
如果您想获得特殊内置函数的列表,您可以例如builtin -s
调用Schily Bourne Shell
.
如果您使用不同的内置函数(例如使用命令)进行测试,您会看到不同的结果,因为只有在经典的 Bourne Shell 上运行测试时,cd
变量赋值才会在命令中保留下来。cd
但请注意,POSIX 允许但不需要 shell 来保持环境special builtins
。如果您希望所有内置函数(甚至是特殊的内置函数)获得相同的行为,您可以在内置函数的名称前面添加command
.