Array intersection in Bash [duplicate]
Solution 1:
The elements of list 1 are used as regular expression looked up in list2 (expressed as string: ${list2[*]} ):
list1=( 1 2 3 4 6 7 8 9 10 11 12)
list2=( 1 2 3 5 6 8 9 11 )
l2=" ${list2[*]} " # add framing blanks
for item in ${list1[@]}; do
if [[ $l2 =~ " $item " ]] ; then # use $item as regexp
result+=($item)
fi
done
echo ${result[@]}
The result is
1 2 3 6 8 9 11
Solution 2:
Taking @Raihan's answer and making it work with non-files (though FDs are created) I know it's a bit of a cheat but seemed like good alternative
Side effect is that the output array will be lexicographically sorted, hope thats okay (also don't kno what type of data you have, so I just tested with numbers, there may be additional work needed if you have strings with special chars etc)
result=($(comm -12 <(for X in "${array1[@]}"; do echo "${X}"; done|sort) <(for X in "${array2[@]}"; do echo "${X}"; done|sort)))
Testing:
$ array1=(1 17 33 99 109)
$ array2=(1 2 17 31 98 109)
result=($(comm -12 <(for X in "${array1[@]}"; do echo "${X}"; done|sort) <(for X in "${array2[@]}"; do echo "${X}"; done|sort)))
$ echo ${result[@]}
1 109 17
p.s. I'm sure there was a way to get the array to out one value per line w/o the for
loop, I just forget it (IFS?)
Solution 3:
Your answer won't work, for two reasons:
-
$array1
just expands to the first element ofarray1
. (At least, in my installed version of Bash that's how it works. That doesn't seem to be a documented behavior, so it may be a version-dependent quirk.) - After the first element gets added to
result
,result
will then contain a space, so the next run ofresult=$result" "$item1
will misbehave horribly. (Instead of appending toresult
, it will run the command consisting of the first two items, with the environment variableresult
being set to the empty string.) Correction: Turns out, I was wrong about this one: word-splitting doesn't take place inside assignments. (See comments below.)
What you want is this:
result=()
for item1 in "${array1[@]}"; do
for item2 in "${array2[@]}"; do
if [[ $item1 = $item2 ]]; then
result+=("$item1")
fi
done
done