我正在使用ksh93中的数组实现各种数据结构(例如堆栈),并且希望避免跟踪索引和计数器,以保持简单。我使用array+=(element)
进行推送,使用print ${array[-1]}
执行 pop ,然后使用unset array[-1]
。
这通常有效,除非在弹出堆栈上的最后一个剩余元素(array[0]
)之后:当我在此之后推送一个项目时,它被分配到索引1,而不是0.例如,如果我运行以下带有PS4='> ' ksh -x
的脚本:
typeset -a foo
foo+=(a b c)
print -C foo
unset foo[-1]
foo+=(d)
print -C foo
unset foo[-1]; unset foo[-1]; unset foo[-1]
print -C foo
print ${#foo[@]}
foo+=(e)
print -C foo
我得到以下输出:
> typeset -a foo
> foo+=( a b c )
> print -C foo
(a b c)
> unset 'foo[-1]'
> foo+=( d )
> print -C foo
(a b d)
> unset 'foo[-1]'
> unset 'foo[-1]'
> unset 'foo[-1]'
> print -C foo
> print 0
0
> foo+=( e )
> print -C foo
([1]=e)
除了最后一次追加操作外,一切都很好。即使数组被验证为空,但它的行为就像在索引0处有一个空元素一样。
我可以解决这个问题,例如不依赖索引0处的第一个项目,或者跟踪索引并执行明确的array[index]=element
赋值,但我仍然想知道是否可以完全避免它。我也知道我可以做set -A array -- "${array[@]}" element
(这可以按预期工作),但这并不像简单的+=
操作那么优雅。我搜索了手册页,Bolsky& Korn书和Rosenblatt&罗宾斯在线预订,但未能在任何地方找到这种行为。
有人知道为什么会这样,和/或如何避免它?谢谢!
答案 0 :(得分:0)
这不是一个解决方案,但它可能会有一些额外的调试步骤。
我总是使用typeset -p
来获取变量的规范表示。如果您在运行上一个unset
后进行尝试,则会看到foo
声明仍然包含0
索引,但没有为其分配值。 (这与分配给它的空字符串不同,它显示为''
。然而,这与各种其他数组内省形式相矛盾,正如您在询问数组计数时所看到的那样。
坦率地说,我认为这可能是ksh中的一个错误,唯一的解决方案可能是将其报告给ast-users mailgroup。
> typeset -a foo
> foo+=(a b c)
> print -C foo
(a b c)
> unset foo[-1]
> foo+=(d)
> print -C foo
(a b d)
> unset foo[-1]; unset foo[-1]; unset foo[-1]
> print -C foo
> print ${#foo[@]}
0
> typeset -p foo
typeset -a foo=([0]=)
> print ${!foo[@]}
> set -u
> print ${foo[0]}
./ksh: foo[0]: parameter not set
>