ksh:将函数输出分配给数组

发布于 2024-08-25 15:59:27 字数 1115 浏览 10 评论 0原文

为什么这不起作用???

#!/bin/ksh

# array testfunc()
function testfunc {
    typeset -A env
    env=( one="motherload" )
            print -r $env
    return 0
}

testfunc # returns: ( one=motherload )
typeset -A testvar # segfaults on linux, memfaults on solaris 
testvar=$(testfunc) # segfaults on linux, memfaults on solaris
print ${testvar.one}

注意:我将上面的脚本从 print $testvar 更新为 print ${testvar.one} ,以更准确地显示我想要完成的任务。

我确信以前已经有人问过这个问题,但我不确定要搜索什么,而且我尝试使用关键字的所有内容都没有给我带来任何与我的问题相关的答案。

ksh 版本:

linux:版本 sh (AT&T Research) 1993-12-28 s+

solaris:版本 sh (AT&T Research) 93s+ 2008-01-31

更新:

所以另一个问题是,这将在 ksh 93t+ 中运行而不会给出错误,但是,它没有正确分配数组。我会从函数中分配一个数组吗?我也尝试像这样分配数组:

typeset -A testvar=$(testfunc)
print ${testvar.one}

但这也无法正常工作。

编辑

那么这里发生了什么?

typeset -A env=( one="motherload" two="vain" )
print ${env.one}
print ${env.two}

我认为这就是你定义关联数组的方式,也许我所看到的已经很旧了,但谁知道......这似乎是奇怪的行为,因为这会打印出“motherload”和“vain”

Why doesn't this work???

#!/bin/ksh

# array testfunc()
function testfunc {
    typeset -A env
    env=( one="motherload" )
            print -r $env
    return 0
}

testfunc # returns: ( one=motherload )
typeset -A testvar # segfaults on linux, memfaults on solaris 
testvar=$(testfunc) # segfaults on linux, memfaults on solaris
print ${testvar.one}

note: I updated the above script to print ${testvar.one} from print $testvar to show more precisely what I am trying to accomplish.

I am sure this has been asked before, but I am not sure what to search on and everything I have been trying to use for keywords is not bringing me any answers that relate to my problem.

ksh version:

linux: version sh (AT&T Research) 1993-12-28 s+

solaris: version sh (AT&T Research) 93s+ 2008-01-31

Update:

So another question is, this will run in ksh 93t+ without giving an error, but, it doesn't assign the array properly. I would I go about assigning an array from a function? I tried assigning the array like this also:

typeset -A testvar=$(testfunc)
print ${testvar.one}

But that also didn't work properly.

EDIT

So what is happening here?

typeset -A env=( one="motherload" two="vain" )
print ${env.one}
print ${env.two}

I thought this was how you defined associative arrays, maybe what I was looking at was old but who knows.... seems odd behaviour since this prints out "motherload" and "vain"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柠檬色的秋千 2024-09-01 15:59:27

您的脚本在使用 ksh 93t+ 的 Linux 上运行良好。

由于它是相同的脚本,并且您在两个不同的环境中遇到类似的错误,因此我怀疑文件中存在杂散字符。尝试其中之一来显示可能存在的任何杂散字符:

hd filename
cat -v filename
hexdump -C filename

如果这只是 DOS 行结尾的问题,那么这将解决这个问题:

dos2unix filename

编辑:

这是在中创建和填充关联数组的一种方法ksh:

$ typeset -A testvar
$ testvar=([one]="motherlode" [two]="vein" [waste]="tailings")
$ echo ${testvar[two]}
vein
$ testvar[ore]="gold"
$ echo ${!testvar[@]}    # print the indices of the array
one two waste ore
$ typeset -p testvar     # show the current definition of the array
typeset -A testvar=([one]="motherlode" [two]="vein" [waste]="tailings" [ore]="gold")

如您所见,ksh 对数组使用括号下标。点分符号用于访问复合变量的成员

我不相信 ksh 函数可以返回数组。但是,您可以使用函数中的打印技术(但在索引名称周围添加方括号)并使用 eval 进行赋值。

$ typeset -A testvar 
$ eval "testvar=($(testfunc))"

或附加到现有数组:

$ eval "testvar+=($(testfunc))"

除非您的函数在内部使用关联数组,否则您不一定需要使用它们来构建输出。

但是,如果这样做,您可以从 typeset -p 的结果进行解析:

$ result=$(typeset -p env)
$ result=${result#*\(}
$ result=${result%\)*}
$ print result

或迭代数组:

$ for index in ${!env[@]}; do print -n "[$index]=${env[$index]} "; done; print

您可能需要查阅有关规则函数和类型变量的文档

Your script works fine for me on Linux with ksh 93t+.

Since it's the same script and you're getting similar errors in two different environments, I would suspect stray characters in the file. Try one of these to show any stray characters that might be present:

hd filename
cat -v filename
hexdump -C filename

If it's simply a matter of DOS line endings, then this will fix that:

dos2unix filename

Edit:

Here's one way to create and populate an associative array in ksh:

$ typeset -A testvar
$ testvar=([one]="motherlode" [two]="vein" [waste]="tailings")
$ echo ${testvar[two]}
vein
$ testvar[ore]="gold"
$ echo ${!testvar[@]}    # print the indices of the array
one two waste ore
$ typeset -p testvar     # show the current definition of the array
typeset -A testvar=([one]="motherlode" [two]="vein" [waste]="tailings" [ore]="gold")

As you can see, ksh uses bracketed subscripts for arrays. Dotted notation is used for accessing members of a compound variable.

I don't believe ksh functions can return arrays. However, you can use the print technique you have in your function (but add square brackets around the index name) and use eval to do the assignment.

$ typeset -A testvar 
$ eval "testvar=($(testfunc))"

or to append to an existing array:

$ eval "testvar+=($(testfunc))"

Unless your function is using associative arrays internally, you don't necessarily need to use them to build your output.

However, if you do, you can parse from the result of typeset -p:

$ result=$(typeset -p env)
$ result=${result#*\(}
$ result=${result%\)*}
$ print result

or iterate through the array:

$ for index in ${!env[@]}; do print -n "[$index]=${env[$index]} "; done; print

You may want to consult the documentation concerning discipline functions and type variables

迷途知返 2024-09-01 15:59:27

这是使用名称引用从函数获取任何返回值的替代方法。返回的值将存储在定义为函数的第一个位置参数的变量中(不预先声明该变量也可以,但该变量将是全局的):

#################################
# Example using compound variable
#################################
function returnCompound {
    typeset -n returnVal="$1"
    returnVal=( one="motherloadCompound" )
    return 0
}

# Declaring the variable to keep it in this scope
# Useful for calling nested functions whitout messing 
# with the global scope
typeset myNewCompoundVar
returnCompound myNewCompoundVar
echo "Compound: ${myNewCompoundVar.one}"

##################################
# Example using asssociative array
##################################
function returnMap {
    typeset -n myNewMapVar="$1"
    myNewMapVar=( [one]="motherloadMap" )

    typeset nestedCompoundVar
    returnCompound nestedCompoundVar
    echo "Compound (Nested) from inside: ${nestedCompoundVar.one}"

    return 0
}

# Declaring the variable to keep it in this scope
# Useful for calling nested functions whitout messing 
# with the global scope 
typeset myNewMapVar
returnMap myNewMapVar
echo "Associative array: ${myNewMapVar[one]}"
echo "Compound (Nested) from outside: ${nestedCompoundVar.one}"

输出:

Compound: motherloadCompound
Compound (Nested) from inside: motherloadCompound
Associative array: motherloadMap
Compound (Nested) from outside: 

重要附注:

  • 函数声明必须使用 function 关键字来完成,否则将不会考虑局部作用域变量的概念。在这种情况下,如果引用变量和全局变量的名称恰好相同,则它们可能会发生冲突,从而导致排版:无效的自引用错误。这可以通过更改“returnMap”函数的声明来测试。
  • 如果在函数调用之前没有声明返回变量,则分配返回值的变量将在全局范围内创建,并且不限于调用范围。

Here is an alternative to getting any return value from a function using name reference. The value returned will be stored in a variable defined as the first positional argument of the function (not declaring the variable beforehand will work but the variable will be global):

#################################
# Example using compound variable
#################################
function returnCompound {
    typeset -n returnVal="$1"
    returnVal=( one="motherloadCompound" )
    return 0
}

# Declaring the variable to keep it in this scope
# Useful for calling nested functions whitout messing 
# with the global scope
typeset myNewCompoundVar
returnCompound myNewCompoundVar
echo "Compound: ${myNewCompoundVar.one}"

##################################
# Example using asssociative array
##################################
function returnMap {
    typeset -n myNewMapVar="$1"
    myNewMapVar=( [one]="motherloadMap" )

    typeset nestedCompoundVar
    returnCompound nestedCompoundVar
    echo "Compound (Nested) from inside: ${nestedCompoundVar.one}"

    return 0
}

# Declaring the variable to keep it in this scope
# Useful for calling nested functions whitout messing 
# with the global scope 
typeset myNewMapVar
returnMap myNewMapVar
echo "Associative array: ${myNewMapVar[one]}"
echo "Compound (Nested) from outside: ${nestedCompoundVar.one}"

Output:

Compound: motherloadCompound
Compound (Nested) from inside: motherloadCompound
Associative array: motherloadMap
Compound (Nested) from outside: 

Important side notes:

  • Function declarations must be done using the function keyword or else the concept of local scope variable won't be taken under account. In which case the name of your reference variable and global variable might clash if they happen to be the same, resulting in a typeset: invalid self reference error. This can be tested by changing the declaration of the 'returnMap' function.
  • If you do not declare the return variable before the function call, the variable to which is assigned the return value will be created globally and not limited to the calling scope.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文