我知道 Bash 和 Zsh 支持local
变量,但是有些系统只有 POSIX 兼容的 shell。并且local
在 POSIX shell 中未定义。
所以我想问一下哪些shell支持local
定义局部变量的关键字?
编辑:关于外壳我的意思是默认/bin/sh
外壳。
我知道 Bash 和 Zsh 支持local
变量,但是有些系统只有 POSIX 兼容的 shell。并且local
在 POSIX shell 中未定义。
所以我想问一下哪些shell支持local
定义局部变量的关键字?
编辑:关于外壳我的意思是默认/bin/sh
外壳。
不是支持不支持那么简单
local
。语法有很多变化,以及在具有一种或其他局部范围的 shell 之间是如何完成的。这就是为什么很难提出一个所有人都同意的标准。有关这方面的 POSIX 工作,请参见http://austingroupbugs.net/bug_view_page.php?bug_id=767。
80 年代初,ksh 中首先添加了本地范围。
在函数中声明局部变量的语法是
typeset
:(函数支持后来被添加到 Bourne shell 中,但是使用了不同的语法 (
f() command
) 并且后来也添加了对该函数的支持ksh
;Bourne shell 从来没有本地范围(当然通过子 shell 除外))local
内置 AFAIK 于 1989 年首次添加到 Almquist shell(用于 BSD、dash、busybox sh)中,但其工作方式ksh
与typeset
.ash
导数不支持typeset
作为 的别名local
,但您始终可以手动定义一个。bash 和 zsh分别在 1989 年和 1991 年添加了
typeset
别名。local
ksh88 添加
local
为typeset
大约 1990 年和 1994 年 pdksh 及其衍生产品的未记录别名。posh
(基于pdksh
)删除typeset
(为了严格遵守需要 Debian 政策local
,但不是typeset
)。POSIX 最初反对指定
typeset
它是动态范围。所以 ksh93(David Korn 在 1993 年对 ksh 的重写)改为使用静态作用域。同样在 ksh93 中,与 ksh88 不同,本地范围仅适用于使用语法 ( ) 声明的函数ksh
,function f {...}
而不是 Bourne 语法 (f() {...}
),并且local
别名已被删除。然而,来自 AT&T 的 ksh93v- beta 和最终版本可以使用实验性的“bash”模式(实际上默认启用)进行编译,该模式
local
在typeset
被ksh93
调用为bash
.local
与typeset
这种情况的不同之处在于它只能从函数内调用。该bash
模式将在 ksh2020 中默认禁用,尽管local
declare
typeset
/别名将保留,即使未编译 bash 模式(尽管仍具有静态范围)。yash
(写得很久以后),有typeset
(à la ksh88),但自 2.48 版(2018 年 12 月)以来,它只是local
作为它的别名。@Schily(遗憾的是,他于 2021 年去世)曾经维护一个 Bourne shell 后代,该后代最近主要符合 POSIX 标准,
bosh
自 2016-07-06 版本起支持本地作用域(带有local
,类似于ash
)。因此,今天具有某种形式的变量局部范围的 Bourne 类 shell 是:
就
sh
不同系统而言,请注意,有些系统(大多数)存在 POSIXsh
,/bin
而其他系统则不存在(例如 Solaris/usr/xpg4/bin
)。对于sh
在各种系统上的实施,我们有:现在,它们的不同之处在于:
typeset
(ksh,pdksh,bash,zsh,yash)与local
(ksh88,pdksh,bash,zsh,ash,yash 2.48+)。function f {...}
函数中)与动态范围(所有其他外壳)。例如,无论是function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f
输出1
还是2
. 另请参阅该export
属性如何影响ksh93
.local
/typeset
只是将变量设为局部变量(ash
,bosh
),还是创建变量的新实例(其他 shell)。例如,是否v=1; f() { local v; echo "${v:-empty}"; }; f
输出1
或empty
(另请参阅localvar_inherit
bash 5.0 及更高版本中的选项)。export
)和/或类型,以及哪些来自父范围内的变量。例如,是否export V=1; f() { local V=2; printenv V; }; f
打印1
,2
或者什么都没有。zsh
)或最初未设置。unset V
是在局部范围内的变量上留下变量unset
,还是只剥离一层范围(在某些情况下,,)mksh
。例如,是否有输出(另请参阅bash 5.0 及更高版本中的选项)yash
bash
v=1; f() { local v=2; unset v; echo "$v"; }
1
localvar_unset
export
,无论是关键字还是仅仅是内置的或两者兼而有之,以及在什么条件下它被视为关键字。export
,参数是被解析为普通命令参数还是赋值(以及在什么条件下)。v=value myfunction
wheremyfunction
本身的交互是否声明v
为本地。这就是我刚才在想的那些。查看上面的 austin group 错误以获取更多详细信息。
至于 shell选项的本地范围(与variables相对),支持它的 shell 是:
ksh88
(使用两种函数定义语法):默认完成,我不知道有什么方法可以禁用它。ash
(自 1989 年以来):与local -
. 它使$-
参数(存储选项列表)本地化。ksh93
: 现在只为function f {...}
函数做。zsh
(自 1995 年以来)。与setopt localoptions
. 还emulate -L
可以将仿真模式(及其选项集)设置为函数的本地。bash
(自 2016 年起)与local -
类似ash
,但仅适用于由 管理的选项set
,而不是由 管理的选项shopt
。¹
sh
Solaris 上的 POSIX 是/usr/xpg4/bin/sh
(尽管它有许多一致性错误,包括函数的本地选项)。/bin/sh
直到 Solaris 10 是 Bourne shell(所以没有本地范围),并且由于 Solaris 11 是 ksh93为了跟进 Stéphane 的回答中的提示,使用 subshells 可以获得本地效果。我无法访问真正的 POSIX shell,但这在busybox 中有效——用括号而不是大括号
ash
声明你的函数。这会强制函数在子 shell 中运行。()
{}
输出
这表明该函数可以访问全局变量,并且在函数中设置变量不会改变全局变量。当我想更改
$IFS
或cd
转到不同的目录时,我有时会使用这种技术,但我不希望这些操作影响程序的其余部分。