shell脚本函数和for循环

时间:2011-04-26 09:11:19

标签: arrays shell

shell脚本中的以下函数只在数组上调用时循环遍历数组的第一个元素,出了什么问题?

#!/bin/sh

in_array(){
    a=$2
    echo ${#a[@]}
    for (( i = 0; i < ${#a[@]} ; i++ ))
    do
        echo ${a[$i]}
        if [ $1 = ${a[$i]} ]
            then
            return 1
        fi
    done
    return 0
}

exclude_dirs=( aaa bbb )
echo ${#exclude_dirs[@]}
in_array home $exclude_dirs

2 个答案:

答案 0 :(得分:1)

有两个问题。第一个是sh不支持数组,因此你的shebang应该改为shell。 (例如,#!/ bin / bash)。第二个问题更为严重。数组不是bash中的第一类对象(它们可能在其他shell中,但我会回答bash的问题,因为sh经常在许多Linux发行版中出现,而我正在使用我的水晶球来确定你的意思是bash当你说#!/ bin / sh)。您可以使用eval获得所需内容。将您的功能更改为以下内容:

in_array(){
    a=$2
    eval "for i in \${$a[@]}; do
        echo \$i
        test $1 = \$i && return 1
    done"
    return 0
}

并在没有'$'的情况下调用它。

in_array home exclude_dirs

另外,我强烈建议反转返回值。 (如果数组中出现$ 1则返回0,否则返回1)。或者,或者将函数名称更改为“not_it_array”。这将允许您编写如下内容:

if in_array home exclude_dirs; then echo home is excluded; fi

(或使用短路&amp;&amp;)。请记住,在sh中,0表示成功,非零表示失败。

当然,通过传递所有值而不是传递名称来传递数组会更容易:

#!/bin/bash

in_array(){
    el=$1
    shift
    while test $# -gt 0; do
        test $el = $1 && return 0
        shift
    done
    return 1
}

exclude_dirs=( aaa home bbb )
in_array home ${exclude_dirs[@]} && echo home is excluded

答案 1 :(得分:0)

William是正确的,你不能在Bourne Shell中使用数组,但你也shouldn't be using eval。为避免这种情况,您可以简化参数结构:

#!/bin/sh

in_array(){
    search_path="$1"
    shift

    while [ -n "${1+defined}" ]
    do
        if [ "$1" = "$search_path" ]
        then
            return 0
        fi
        shift
    done
    return 1
}

in_array foo aaa bbb && echo fail test 1
in_array foo foo bar || echo fail test 2
in_array foo bar foo || echo fail test 3
in_array foo foobar && echo fail test 4
in_array foo barfoo && echo fail test 5
in_array foo "foo bar" && echo fail test 6
in_array "foo bar" "foo bar" "baz ban" || echo fail test 7
true