KSH 中变量的范围

问题描述 投票:0回答:2

我编写了一个示例 KornShell 函数来拆分字符串,将其放入数组中,然后打印出值。 代码如下

#!/usr/bin/ksh

splitString() {

    string="[email protected];[email protected];[email protected]"

    oIFS="$IFS"; 
    IFS=';' 
    set -A str $string
    IFS="$oIFS"
}

splitString
echo "strings count = ${#str[@]}"
echo "first : ${str[0]}";
echo "second: ${str[1]}";
echo "third : ${str[2]}";

现在

echo
不会打印出数组的值,所以我认为它与定义的数组的范围有关。

我是 Shell 脚本新手,有人可以帮我理解上面示例中变量的范围吗?

shell unix scripting ksh
2个回答
17
投票

变量的默认作用域是整个脚本。

但是,当您在函数内声明变量时,该变量将成为声明它的函数的局部变量。 Ksh 具有“动态作用域”,因此该变量也可以在声明该变量的函数调用的函数中访问。 手册中的功能部分对此进行了简要记录。请注意,在 AT&T ksh 中(与 pdksh 和衍生物相对,以及 bash 和 zsh 的类似功能),这仅适用于使用 function 关键字定义的函数,不适用于使用传统

f () { … }
语法定义的函数。在 AT&T ksh93 中,使用传统语法定义的函数中声明的所有变量都是全局变量。
声明变量的主要方式是使用 

typeset

builtin
。它始终使变量成为本地变量(在 AT&T ksh 中,仅在使用 function 声明的函数中)。如果您分配给变量而没有使用
typeset
声明它,则它是全局的。
ksh 文档没有指定 

set -A

是否使变量成为本地变量或全局变量,并且不同的版本也可以这样做。在 ksh 93u、pdksh 或 mksh 下,该变量是全局变量,您的脚本会打印出该值。您似乎拥有 ksh88 或旧版本的 ksh,其范围是本地的。我认为在函数外部初始化

str
会创建一个全局变量,但我不确定。
请注意,您应该使用局部变量来覆盖 

IFS

的值:保存到另一个变量不仅笨拙,而且很脆弱,因为如果未设置,它无法正确恢复

IFS
。此外,您应该关闭通配符,因为否则如果字符串包含 shell 通配符
?*\[
并且其中一个单词恰好与系统上的一个或多个文件匹配,它将被扩展,例如
set -A $string
,其中
string
a;*
将导致
str
包含当前目录中的文件名列表。
set -A str
function splitString {
  typeset IFS=';' globbing=1
  case $- in *f*) globbing=;; esac
  set -f
  set -A str $string
  if [ -n "$globbing" ]; then set +f; fi
}
splitString "$string"



3
投票

typeset

命令可以使它们位于定义它们的函数的本地,或者使它们自动导出(即使它们已更新)。


阅读手册页或 Korn 的书中的“typeset”和“integer”。

© www.soinside.com 2019 - 2024. All rights reserved.