Shell

ksh93 中的排版無法按預期工作

  • January 28, 2019

我以為typesetksh’s local,但這失敗了,ksh93 儘管它適用於我所有其他支持的typesetshell(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 ]

是什麼賦予了?

typeset是 ksh93 private(使用像perl‘s這樣的靜態作用域my,而不是local動態作用域)僅適用於使用 ksh 函式定義樣式聲明的函式:

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現在有一個private關鍵字具有與ksh93’s 類似的作用域,除了local/typeset具有動態作用域,如 in ksh88

要查看靜態和動態範圍之間的區別,請比較:

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

帶有$shell==的ksh93輸出:

0
1

並帶有ksh88bash輸出:

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 ksh93、或/ sh 的程式碼中使用本地範圍pdksh,您可以執行以下操作:yash``dash``FreeBSD

[ -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 中的行為之間存在許多差異。除了上面提到的動態與靜態考慮之外,變數最初是否獲得未設置或空值或從父範圍繼承值。還有與 , 的互動readonlyunset無論local/typeset是關鍵字還是內置(影響 split+glob 處理)…

在 中使用 ksh 樣式的函式定義還有其他含義ksh93,請參閱手冊頁了解詳細資訊。

更多閱讀

引用自:https://unix.stackexchange.com/questions/375156