ksh93 中的排版未按预期工作

ksh93 中的排版未按预期工作

我以为typesetksh's local,但这失败了,ksh93 尽管它在我所有其他typeset支持 shell(bash、yash、zsh、pdksh)中都有效

#!/bin/ksh -ex

foo(){
    typeset a b
    a=0; b=1
    return
}
a=a; b=b
foo
#confirm that the globals didn't change
[ "$a" = a ] 
[ "$b" = b ]

是什么赋予了?

答案1

typeset是 ksh93 的(使用像sprivate一样的静态作用域,而不是动态作用域)仅适用于使用 ksh 函数定义样式声明的函数:perlmylocal

function foo {
  typeset var=whatever
  ...
}

使用 Bourne 语法(或使用命令.(顺便说一句,也可以在 ksh 样式函数上使用)),没有作用域(当然,除了$1, $2... $#)。因此,可以使用 Bourne 风格的函数来获取值或更改父上下文中变量的值或类型(尽管typeset -n也可以与 ksh 风格一起使用)。

在 ksh88 中,typeset使用 ksh 和 Bourne 函数定义样式进行动态作用域。根据 David Korn 的说法,POSIX 没有指定 ksh 的变量范围,因为它是动态的(被认为较差)这就是为什么他将其更改为静态作用域ksh93(完全重写)。

但与此同时,其他 shell 也实现了变量作用域,并且它们都使用动态的范围模仿 ksh88。

zsh现在有一个关键字,除了/具有类似于 in 的动态作用域之外private,还具有类似于 s 的作用域。ksh93localtypesetksh88

要查看静态作用域和动态作用域之间的差异,请比较:

"$shell" -c 'function f { typeset a=1; g; echo "$a"; }
             function g { echo "$a"; a=2; }
             a=0; f'

其中$shell==ksh93输出:

0
1

并带有ksh88orbash输出:

1
2

zsh

$ zsh -c 'zmodload zsh/param/private
          f() { private a=1; g; echo $a;}
          g() { echo $a; a=2; }
          a=0; f'
0
1

为了能够在可移植到bashzshksh88 ksh93pdksh或/ shyash的代码中使用本地作用域,您可以这样做:dashFreeBSD

[ -n "$BASH_VERSION" ] && shopt -s expand_aliases
alias shdef= kshdef='#'
if type typeset > /dev/null 2>&1; then
  alias mylocal=typeset
  if (a=1; f() { typeset a=2; }; f; [ "$a" = 2 ]); then
    alias shdef='#' kshdef='function'
  fi
else
  alias mylocal=local
fi

然后将您的函数声明为:

kshdef foo
shdef foo()
{
  mylocal var
  var=value
  ...
}

无论如何,local不​​同 shell 中的行为之间存在许多差异。除了上面提到的动态与静态考虑之外,还有变量最初是否获得未设置或空值或从父作用域继承该值。还有与readonly,的交互unset,无论local/typeset是关键字还是内置的(影响 split+glob 处理)...

在 中使用 ksh 风格的函数定义还有其他含义ksh93,有关详细信息,请参阅手册页。

更多阅读

相关内容