Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array intersection in Bash [duplicate]

Tags:

How do you compare two arrays in Bash to find all intersecting values?

Let's say:
array1 contains values 1 and 2
array2 contains values 2 and 3

I should get back 2 as a result.

My own answer:

for item1 in $array1; do     for item2 in $array2; do         if [[ $item1 = $item2 ]]; then             result=$result" "$item1         fi     done done 

I'm looking for alternate solutions as well.

like image 723
dabest1 Avatar asked Oct 24 '11 00:10

dabest1


Video Answer


2 Answers

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 
like image 105
Fritz G. Mehner Avatar answered Oct 08 '22 19:10

Fritz G. Mehner


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?)

like image 24
nhed Avatar answered Oct 08 '22 18:10

nhed