I have two commands. The first, when stored in a script variable, gives output like this:
one two three four five
The second also gives a list, but some of the items may be missing that were in the first command:
one three five
I want my script to do something if an item is in the first command but not the second. None of the items will have spaces (they tend to be kabab-format
). How can I do this in Bash?
One approach using the current variables, and relying on the fact that individual values do not contain embedded white space:
$ var1='one two three four five'
$ var2='one three five'
$ comm -23 <(printf "%s\n" ${var1} | sort) <(printf "%s\n" ${var2} | sort)
four
two
NOTE: do not wrap the ${var1}
and ${var2}
references in double quotes, ie, we want word splitting to occur when feeding the printf
calls
Another idea using an associative array to track unique values:
var1='one two three four five'
var2='one three five'
unset arr
declare -A arr
for f in ${var1} # use ${var1} values as indices for arr[]
do
arr[${f}]=1 # '1' has no meaning other than to fill requirement of assigning a value in order to create the array entry
done
for f in ${var2} # delete ${var2} indices from arr[]
do
unset arr[${f}]
done
for i in "${!arr[@]}" # display arr[] indices that remain
do
echo "${i}"
done
# one-liners (sans comments)
for f in ${var1}; do arr[${f}]=1; done
for f in ${var2}; do unset arr[${f}]; done
for i in "${!arr[@]}"; do echo "${i}"; done
This generates:
two
four
NOTES:
${var1}
and ${var2}
references in double quotes, ie, we want word splitting to occurawk
scriptarr[]
from ${var1}
) will eliminate duplicates from ${var1}
, eg, var1='one one one'
would lead to a single array entry: arr[one]=1