Validate a string against an array

Viewed 61

I have a string like this:

array_string="a b"

I have an array like this:

array=(a b c)

I want to verify that all the elements of array_string are included in array if so I can overwrite the array with the element included in the array_string:

array=($array_string)

Which is the best way to do such a validation?

3 Answers

You may use grep with couple of process substitutions:

grep -qvf <(printf '%s\n' "${array[@]}") <(echo "${array_string// /$'\n'}") ||
echo "all elements of array_string are present in array"

For string-to-array comparison the following example uses space as the separator and expects it to be at the start and end of the list so that every value will be wrapped between two separators. It also avoids using an external process or subshell.

for ((index=0; index < "$((${#array[@]}"; index++)); do
  if [[ "$array_string" != *" ${array[$index]} "* ]]; then
    return 1
  fi
done

For an array-to-array comparison it's easy to convert the string to an array after removing the leading separator, and then use a nested loop to compare them. This can also avoid using an external process or subshell as read is a bash builtin:

# Needs to read to a different variable so it
#   doesn't empty the source and read nothing.
IFS=' ' read -ra string_array <<< "${array_string# }"
found=1
for ((x=0; x < "${#string_array[@]}"; x++)); do
  for ((y=0; y < "${#array[@]}"; y++)); do
    if [[ "${string_array[$x]}" == "${array[$y]}" ]]; then
      found=0
    fi
  done

  if [[ found -ne 0 ]]; then
    return 1
  fi

  found=1
done

You can determine the items which exist in the array_string but don't exist in the array like this:

join -v1 <(sort -b <<< "${array_string// /$'\n'}") <(IFS=$'\n'; sort -b <<< "${array[*]}")

with the assumption that items don't contain spaces. Using this, you can do:

if [[ -z $(join -v1 <(sort -b <<< "${array_string// /$'\n'}") <(IFS=$'\n'; sort -b <<< "${array[*]}")) ]]
then
    echo "array_string is a subset of array"
else
    echo "array_string is NOT a subset of array"
fi
Related