Получить общие значения в 2 массивах в сценариях оболочки
У меня есть
array1 = (20,30,40,50)
array2 = (10,20,30,80,100,110,40)
Я должен получить общие значения из этих 2 массивов в моем массиве 3, как:
array3 = (20,30,40)
в порядке сортировки по возрастанию.
7 ответов
Оболочки и стандартные утилиты Unix хорошо справляются с текстовыми файлами.
В этой области массивами будут текстовые файлы, элементами которых являются строки.
Чтобы найти общую часть между двумя такими массивами, есть стандарт comm
команда. comm
хотя ожидается сортировка по алфавиту.
Итак, если у вас есть два файла A
а также B
содержащий элементы этих двух массивов, по одному на строку (что также означает, что элементы массива не могут содержать символы новой строки), вы можете найти пересечение с
comm -12 <(sort A) <(sort B)
Если вы хотите начать с bash
массивы (но использование массивов в оболочках - это, как правило, хороший признак того, что вы используете не тот инструмент для своей задачи), вы можете конвертировать туда и обратно между bash
массивы и наши текстовые файлы массивы строк с printf '%s\n'
и разделение слов:
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)))
Вы почти наверняка не должны использовать оболочку для этого, так что вот ЕДИНСТВЕННОЕ решение для вашей конкретной проблемы:
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
и если вы скажете нам, что вы действительно пытаетесь сделать, вы можете получить гораздо больше помощи.
Чистое решение bash с использованием массивов:
#!/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[*]}
Выход
20 30 40
Как array3
не является ассоциативным массивом, индексы идут в порядке возрастания, используя ${!array[*]}
нотации. Если вам нужен список через запятую в качестве входных данных, используйте echo "${array3[*]}"
,
Может использоваться, если исходные элементы являются целыми числами. Это работает, только если каждый из исходных массивов содержит уникальные числа.
Рассмотрите возможность использования python:
In [6]: array1 = (20,30,40,50)
In [7]: array2 = (10,20,30,80,100,110,40)
In [8]: set(array1) & set(array2)
Out[8]: set([40, 20, 30])
В дополнение к любому из этих хороших ответов кажется, что вы также хотите отсортировать ваш массив (содержащий ответ) в порядке возрастания.
Вы можете сделать это разными способами, в том числе:
readarray array3 <<<"$(printf "%s\n" "${array3[@]}" | sort -n)"
Этот метод также позволяет отфильтровывать повторяющиеся значения:
readarray array3 <<<"$(printf "%s\n" "${array3[@]}" | sort -n | uniq)"
И ради упражнения вот еще один способ его решения:
#!/bin/bash
array1=(20 30 40 50)
array2=(10 20 30 80 100 110 40)
declare -a array3
#sort both arrays
readarray array1 <<<"$(printf "%s\n" "${array1[@]}" | sort -n)"
readarray array2 <<<"$(printf "%s\n" "${array2[@]}" | sort -n)"
# look for values
i2=0
for i1 in ${!array1[@]}; do
while (( i2 < ${#array2[@]} && ${array1[$i1]} > ${array2[$i2]} )); do (( i2++ )); done
[[ ${array1[$i1]} == ${array2[$i2]} ]] && array3+=(${array1[$i1]})
done
echo ${array3[@]}
Может быть, вы можете использовать Perl для попытки.
#!/bin/perl
use warnings;
use strict;
my @array1 = (20,30,40,50);
my @array2 = (10,20,30,80,100,110,40);
my @array3 = ();
foreach my $x (@array1) {
# body...
if (grep(/$x/, @array2)){
print "found $x\n";
@array3=(@array3,$x);
};
}
print @array3
Вот решение со стандартными инструментами командной строки (sort
а также join
):
join <(printf %s\\n "${array1[@]}" | sort -u) \
<(printf %s\\n "${array2[@]}" | sort -u) | sort -n
join
требует сортировки входных данных и не распознает числовой порядок сортировки. Следовательно, я сортирую оба списка в порядке сортировки по умолчанию, присоединяюсь к ним, а затем прибегаю к числовому результату.
Я также предположил, что вы создали массивы действительно как массивы, то есть:
array1=(20 30 40 50)
Я думаю, что остальное более или менее самоочевидно, возможно, с помощью help printf
а также man bash
,