Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get common values in 2 arrays in shell scripting [duplicate]

I have an

array1 = (20,30,40,50)
array2 = (10,20,30,80,100,110,40)

I have to get the common values from these 2 arrays in my array 3 like:

array3 = (20,30,40) 

in ascending sorted order.

like image 982
iaav Avatar asked Jun 10 '13 21:06

iaav


3 Answers

Shell and standard Unix utilities are good at dealing with text files.

In that realm, arrays would be text files whose elements are the lines.

To find the common part between two such arrays, there's the standard comm command. comm expects alphabetically sorted input though.

So, if you have two files A and B containing the elements of those two arrays, one per line (which also means the array elements can't contain newline characters), you can find the intersection with

comm -12 <(sort A) <(sort B)

If you want to start with bash arrays (but using arrays in shells is generally a good indication that you're using the wrong tool for your task), you can convert back and forth between the bash arrays and our text file arrays of lines with printf '%s\n' and word splitting:

array_one=(20 30 40 50)
array_two=(10 20 30 80 100 110 40)
IFS=$'\n'; set -f
intersection=($(comm -12 <(
   printf '%s\n' "${array_one[@]}" | sort) <(
   printf '%s\n' "${array_two[@]}" | sort)))
like image 173
Stephane Chazelas Avatar answered Nov 18 '22 12:11

Stephane Chazelas


You almost certainly should not be using shell for this so here's ONE awk solution to your specific problem:

awk 'BEGIN{
    split("20,30,40,50",array1,/,/)
    split("10,20,30,80,100,110,40",array2,/,/)

    for (i=1;i in array1;i++)
        for (j=1;j in array2;j++)
            if (array1[i] == array2[j])
                array3[++k] = array1[i]

    for (k=1; k in array3; k++)
        printf "array3[%d] = %d\n",k,array3[k]
}'
array3[1] = 20
array3[2] = 30
array3[3] = 40

and if you tell us what you're really trying to do you can get a lot more help.

like image 30
Ed Morton Avatar answered Nov 18 '22 12:11

Ed Morton


A pure bash solution using arrays:

#!/bin/bash

array1=(20,30,40,50)
array2=(10,20,30,80,100,110,40)

IFS=,
for i in $array1 $array2;{ ((++tmp[i]));}
for i in ${!tmp[*]};{ [ ${tmp[i]} -gt 1 ] && array3+=($i);}
echo ${array3[*]}

Output

20 30 40

As array3 is not an associative array, the indexes comes in ascending order using ${!array[*]} notation. If You need comma separated list as input, use echo "${array3[*]}".

It can be used if the source elements are integers. It works only if each of the source arrays contain unique numbers..

like image 2
TrueY Avatar answered Nov 18 '22 10:11

TrueY