In bash, I know to be able to find the unique values between two arrays can be found by:
echo "${array1[@]} ${array2[@]}" | tr ' ' '\n' | sort | uniq -u
However, this gives the unique values between BOTH arrays. What if I wanted something about the elements that are unique only to array1 and elements that are unique only to array2? For example:
array1=(1 2 3 4 5)
array2=(2 3 4 5 6)
original_command_output = 1 6
new_command_output1 = 1
new_command_output2 = 6
CodePudding user response:
You could use the comm
command.
To get elements unique to the first array:
comm -23 \
<(printf '%s\n' "${array1[@]}" | sort) \
<(printf '%s\n' "${array2[@]}" | sort)
and elements unique to the second array:
comm -13 \
<(printf '%s\n' "${array1[@]}" | sort) \
<(printf '%s\n' "${array2[@]}" | sort)
Or, more robust, allowing for any character including newlines to be part of the elements, split on the null byte:
comm -z -23 \
<(printf '%s\0' "${array1[@]}" | sort -z) \
<(printf '%s\0' "${array2[@]}" | sort -z)
CodePudding user response:
comm
is probably the way to go but if you're running bash >= 4 then you can do it with associative arrays:
#!/bin/bash
declare -a array1=(1 2 3 4 5) array2=(2 3 4 5 6)
declare -A uniq1=() uniq2=()
for e in "${array1[@]}"; do uniq1[$e]=; done
for e in "${array2[@]}"; do
if [[ ${uniq1[$e]-1} ]]
then
uniq2[$e]=
else
unset "uniq1[$e]"
fi
done
echo "new_command_output1 = ${!uniq1[*]}"
echo "new_command_output2 = ${!uniq2[*]}"
new_command_output1 = 1
new_command_output2 = 6
CodePudding user response:
Personally I would stick to BASH builtins. This will read each character number in arr1 comparing it to the numbers in arr2. If numbers are ordered differently than it will output those numbers as well as any unique numbers
arr1=(1 2 3 4 5)
arr2=(1 3 2 4)
for i in ${arr1[@]} ; do
[[ $i == ${arr2[i-1))]} ]] || echo $i
done
output: 2 3 5
If you want to get unique numbers not based on location, you can do this instead:
for i in ${arr1[@]} ; do
read n <<<${arr2[i-1]}
[[ ${arr1[@]} =~ $n ]] || echo $i
done
output: 5