在Zsh中使用“声明”

时间:2019-04-10 14:43:08

标签: zsh

我正在关注此线程:https://stackoverflow.com/a/19742842/5057251 在ZSH(而不是BASH)中排版(或声明)。

#Declare (or typeset) an array of integers
#declare -ai int_array
typeset -ai int_array
int_array=(1 2 3)
echo "${int_array[@]}"

然后

# Attempt to change 1st element to string. (expect to fail)
int_array[1]="Should fail" || echo "error: ${LINENO}"
echo "${int_array[@]}"

Bash发现错误,优雅地报告错误和lineno,并打印:

1 2 3

但是Zsh接受并打印:

Should fail 2 3

不确定为什么不同。

2 个答案:

答案 0 :(得分:0)

这里有两个问题:

  1. 在bash和zsh中,将字符串分配给整数变量会使该字符串作为算术表达式求值。因此,这不是错误:

    $ typeset -i foo
    $ foo="bar"
    

    如果bar是先前设置为算术表达式的变量,则bar的扩展将按以下方式求值:

    $ bar=10+2
    $ typeset -i foo
    $ foo="bar"
    $ echo "$foo"
    12
    

    您分配的错误当然是没有办法像这样展开Should fail。例如,如果它是Should - fail(算术表达式减去两个变量Shouldfail的值,它将仍然有效:

    $ foo="Should - fail"
    $ echo "$foo"
    0
    
  2. 第二个问题是the zsh docs中没有任何内容指示可以为整个数组设置-i,因此-a中的-ai被忽略:

    bash-5.0$ typeset -ai foo
    bash-5.0$ declare -p foo
    declare -ai foo=([0]="0")  # the previous value was retained in the array
    

    vs zsh:

    % typeset -ai foo
    % foo[1]=10
    % foo[2]=20
    % declare -p foo
    typeset -i foo=20  # treated as a normal variable, not array
    

    您看到的实际上是int_array在执行int_array=(1 2 3)时被重新声明为数组(没有任何限定符):

    % foo=(1 2 3)
    % declare -p foo
    typeset -a foo=( 1 2 3 )
    

答案 1 :(得分:0)

使用zsh排版可能会产生一些可能的结果:
 -没有错误,有效(是!)。
 -错误,脚本失败(修复!)。
 -没有错误,但意外行为。 (抓头)

作为最后一个类别的示例,这不会产生任何错误,但是typeset -p显示-i被忽略。

{                                                                                                                                                                        
unset int_array                                                                                                                                                          
typeset -ia int_array                                                                                                                                                    
int_array=(1 2 3)                                                                                                                                                        
echo $? "-Point A"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     

    } always {                                                                                                                                                           

echo $? "-Point B"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     
(( TRY_BLOCK_ERROR=0 ))                                                                                                                                                  
}                                                                                                                                                                        
echo $? "-Point C"                                                                                                                                                       
echo "survived"                                                                                                                                                          

产生

 0 -Point A                                                                                                                                                               
 typeset -a int_array=( 1 2 3 )                                                                                                                                           
 0 -Point B                                                                                                                                                               
 typeset -a int_array=( 1 2 3 )                                                                                                                                           
 0 -Point C                                                                                                                                                               
 survived                                                                                                                                                                 

第一行取消设置int_array。 typeset命令声明
 int_array既是数组又是int,这不是zsh允许的。下一个
 行将int_array分配给一个值。 $?告诉我们没有错误,
 但仔细检查最终typeset -p int_array会发现实际上是什么
 发生了

稍作更改,我们就会产生错误并使用always块和
 typeset -p来查找更多详细信息。

{                                                                                                                                                                        
unset int_array                                                                                                                                                          
typeset -ia int_array=(1 2 3) # error                                                                                                                                    
echo $? "-Point A"                                                                                                                                                       
typeset -p int_array 

      } always {                                                                                                                                                           

echo $? "-Point B"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     
(( TRY_BLOCK_ERROR=0 ))                                                                                                                                                  
}                                                                                                                                                                        
echo $? "-Point C"                                                                                                                                                       
echo "survived"                                                                                                                                                          
040_declare_version2.sh:typeset:135: int_array: inconsistent type for assignment                                                                                         
1 -Point B                                                                                                                                                               
040_declare_version2.sh:typeset:140: no such variable: int_array                                                                                                         
1 -Point C                                                                                                                                                               
survived                                                                                                                                                                 

唯一的区别是错误的typeset -ia语句中给int_array一个值。
 这会产生错误,并且脚本会跳至always block.
 (( TRY_BLOCK_ERROR=0))允许脚本继续
 并且不会终止,但是错误仍然报告在“ C点”。

要检查外壳版本:

$SHELL --version                                                                                                                                                         
zsh 5.4.2 (x86_64-ubuntu-linux-gnu)