Check if a Bash array contains a value

前端 未结 30 2745
执笔经年
执笔经年 2020-11-22 07:14

In Bash, what is the simplest way to test if an array contains a certain value?

30条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-22 07:52

    Borrowing from Dennis Williamson's answer, the following solution combines arrays, shell-safe quoting, and regular expressions to avoid the need for: iterating over loops; using pipes or other sub-processes; or using non-bash utilities.

    declare -a array=('hello, stack' one 'two words' words last)
    printf -v array_str -- ',,%q' "${array[@]}"
    
    if [[ "${array_str},," =~ ,,words,, ]]
    then
       echo 'Matches'
    else
       echo "Doesn't match"
    fi
    

    The above code works by using Bash regular expressions to match against a stringified version of the array contents. There are six important steps to ensure that the regular expression match can't be fooled by clever combinations of values within the array:

    1. Construct the comparison string by using Bash's built-in printf shell-quoting, %q. Shell-quoting will ensure that special characters become "shell-safe" by being escaped with backslash \.
    2. Choose a special character to serve as a value delimiter. The delimiter HAS to be one of the special characters that will become escaped when using %q; that's the only way to guarantee that values within the array can't be constructed in clever ways to fool the regular expression match. I choose comma , because that character is the safest when eval'd or misused in an otherwise unexpected way.
    3. Combine all array elements into a single string, using two instances of the special character to serve as delimiter. Using comma as an example, I used ,,%q as the argument to printf. This is important because two instances of the special character can only appear next to each other when they appear as the delimiter; all other instances of the special character will be escaped.
    4. Append two trailing instances of the delimiter to the string, to allow matches against the last element of the array. Thus, instead of comparing against ${array_str}, compare against ${array_str},,.
    5. If the target string you're searching for is supplied by a user variable, you must escape all instances of the special character with a backslash. Otherwise, the regular expression match becomes vulnerable to being fooled by cleverly-crafted array elements.
    6. Perform a Bash regular expression match against the string.

提交回复
热议问题