linux shell tips

Bash Bits: Check if item is in array

This is a simple function which helps you find out if an (non associative) array has an item. It allows you to call the function with just the array name, not ${arrayname[@]}. It returns 1 if the item is in the array, and 0 if it is not.

This is the function:

in_array() {
    local haystack=${1}[@]
    local needle=${2}
    for i in ${!haystack}; do
        if [[ ${i} == ${needle} ]]; then
            return 0
        fi
    done
    return 1
}

Now we can test it and see that it works:

declare -a vpsservers=("vps1" "vps2" "vps3" "vps4" "vps6");

in_array vpsservers vps3 && echo "found" || echo "not found"
in_array vpsservers vps5 && echo "found" || echo "not found"

Should return:

found
not found

Now a usage example. Lets say you have a script which requires a specific version of Ubuntu and does not work on other versions of ubuntu. You can use this to check if the version of ubuntu is supported with this function.

declare -a supported_ubuntu=("Ubuntu 10.04.1 LTS" "Ubuntu 10.04.3 LTS" "Ubuntu 10.04.4 LTS" "Ubuntu 10.10" "Ubuntu 12.04 LTS" "Ubuntu 12.04.1 LTS")

if [ -f "/etc/lsb-release" ]; then
    running_ubuntu=`awk -F "\"" '/DESCRIPTION/ { print $2 }' /etc/lsb-release`
    if in_array supported_ubuntu "${running_ubuntu}"; then
        echo "${running_ubuntu} is supported."
    else
        echo "${running_ubuntu} is not supported. Run ${0} again with the -f option to ignore this warning."
        exit 1
    fi
fi

Do note that forcing a specific version of something is not a best practice, however sometimes you are forced to.

Write a separate function in_array:

# Check if a value exists in an array
# @param $1 mixed  Needle  
# @param $2 array  Haystack
# @return  Success (0) if value exists, Failure (1) otherwise
# Usage: in_array "$needle" "${haystack[@]}"
# See: http://fvue.nl/wiki/Bash:_Check_if_array_element_exists
in_array() {
    local hay needle=$1
    shift
    for hay; do
        [[ $hay == $needle ]] && return 0
    done
    return 1
}

Tests:

$ aa=(foo bar "cee dee" eek "2 3" 34 4)
$ in_array bar       "${aa[@]}" && echo yes || echo no
yes
$ in_array cee       "${aa[@]}" && echo yes || echo no
no
$ in_array "cee dee" "${aa[@]}" && echo yes || echo no
yes
$ in_array 3         "${aa[@]}" && echo yes || echo no
no
$ in_array 4         "${aa[@]}" && echo yes || echo no
yes
function contains() {
    local n=$#
    local value=${!n}
    for ((i=1;i < $#;i++)) {
        if [ "${!i}" == "${value}" ]; then
            echo "y"
            return 0
        fi
    }
    echo "n"
    return 1
}

A=("one" "two" "three four")
if [ $(contains "${A[@]}" "one") == "y" ]; then
    echo "contains one"
fi
if [ $(contains "${A[@]}" "three") == "y" ]; then
    echo "contains three"
fi

发表评论