5

我有一个

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

我必须从数组 3 中的这两个数组中获取公共值,例如:

array3 = (20,30,40) 

按升序排列。

4

7 回答 7

4

Shell 和标准 Unix 实用程序擅长处理文本文件。

在那个领域,数组将是文本文件,其元素是行。

要找到两个这样的数组之间的共同部分,可以使用标准comm命令。comm期望按字母顺序排序的输入。

因此,如果您有两个文件AB包含这两个数组的元素,每行一个(这也意味着数组元素不能包含换行符),您可以找到与

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

如果您想从数组开始(但在 shell 中使用数组通常表明您使用了错误的工具来完成任务),您可以在数组和我们的文本文件数组之间bash来回转换分裂:bashprintf '%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)))
于 2013-06-10T21:38:39.150 回答
3

您几乎可以肯定不应该为此使用 shell,所以这里有一个针对您的特定问题的 awk 解决方案:

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

如果你告诉我们你真正想要做什么,你可以获得更多帮助。

于 2013-06-10T23:02:00.630 回答
2

使用数组的纯

#!/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[*]}".

如果源元素是整数,则可以使用它。它仅在每个源数组都包含唯一编号时才有效。

于 2013-06-10T21:51:59.830 回答
0

除了这些好的答案之外,您似乎还想按升序对数组(包含答案)进行排序。

您可以通过多种不同的方式做到这一点,包括:

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[@]}
于 2013-06-10T22:00:57.197 回答
0

这是使用标准命令行工具(sortjoin)的解决方案:

join <(printf %s\\n "${array1[@]}" | sort -u) \
     <(printf %s\\n "${array2[@]}" | sort -u) | sort -n

join要求对其输入进行排序,并且不识别数字排序顺序。因此,我以默认排序顺序对两个列表进行排序,将它们连接起来,然后以数字方式对结果进行排序。

我还假设您将数组真正创建为数组,即:

array1=(20 30 40 50)

我认为其余的或多或少是不言而喻的,可能在 and 的帮助help printfman bash

于 2013-06-10T23:44:41.537 回答
0

也许您可以使用 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
于 2013-06-11T06:32:17.697 回答
-1

考虑使用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])
于 2013-06-10T21:28:57.673 回答