简体   繁体   中英

Find items common between two Bash arrays

I have below shell script in which I have two arrays number1 and number2 . I have a variable range which has list of numbers.

Now I need to figure out what are all numbers which are in number1 array are also present in range variable. Similarly for number2 array as well. Below is my shell script and it is working fine.

number1=(1220 1374 415 1097 1219 557 401 1230 1363 1116 1109 1244 571 1347 1404)
number2=(411 1101 273 1217 547 1370 286 1224 1362 1091 567 561 1348 1247 1106 304 435 317)
range=90,197,521,540,552,554,562,569:570,573,576,579,583,594,597,601,608:609,611,628,637:638,640:641,644:648
range_f=" "$(eval echo $(echo $range | perl -pe 's/(\d+):(\d+)/{$1..$2}/g;s/,/ /g;'))" "
echo "$range_f"

for item in "${number1[@]}"; do
 if [[ $range_f =~ " $item " ]] ; then
 new_number1+=($item)
 fi
done
echo "new list: ${new_number1[@]}"

for item in "${number2[@]}"; do
 if [[ $range_f =~ " $item " ]] ; then
   new_number2+=($item)
 fi
done
echo "new list: ${new_number2[@]}"

Is there any better way to write above stuff? As of now I have two for loops iterating and then figuring out new_number1 and new_number2 arrays.

Note: Numbers like 644:648 means, it starts with 644 and ends with 648. It is just short form.

You can use comm with process substitution instead of looping:

mapfile -t new_number1 < <(comm -12 <(printf '%s\n' "${number1[@]}" | sort) <(printf '%s\n' $range_f | sort))
mapfile -t new_number2 < <(comm -12 <(printf '%s\n' "${number2[@]}" | sort) <(printf '%s\n' $range_f | sort))
  • mapfile -t name reads from the nested process substitution into the named array
  • printf ... | sort printf ... | sort pair provides the sorted input streams for comm
  • comm -12 emits the items common to the two streams

Aside from codeforester's answer, I can think of two other ways of doing this:

  1. Load the values of $range as keys of an associative array. The values will be 1 . Loop through each member of ${number1[@]} and ${number2[@]} , testing them against the values in the associative array.
  2. Use codeforester's printf ... | sort printf ... | sort trick, but pipe both the list and the range through sort | uniq -c sort | uniq -c , then grep for the duplicates.

I'm not sure if either one of these is an actual improvement on your code. ... I would create a 'find duplicates' shell function, but otherwise your code looks solid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM