使用Shell脚本比较两个不同的数组

时间:2018-09-24 21:23:53

标签: shell sh ksh

我们如何比较两个数组并将结果显示在shell脚本中?

假设我们有两个如下数组:

list1=( 10 20 30 40 50 60 90 100 101 102 103 104)
list2=( 10 20 30 40 50 60 70 80 90 100 )

我的要求是按顺序比较这两个数组,以便仅将结果显示为(101 102 103 104)中的list1。它不应该包含70中存在的值80list2,但list1中不存在。

这无济于事,因为它包含了所有内容:

echo "${list1[@]}" "${list2[@]}" | tr ' ' '\n' | sort | uniq -u

我在下面尝试了类似的方法,但是为什么不起作用?

list1=( 10 20 30 40 50 60 70 90 100 101 102 103 104)
list2=( 10 20 30 40 50 60 70 80 90 100 )

for (( i=0; i<${#list1[@]}; i++ )); do
for (( j=0; j<${#list2[@]}; j++ )); do
     if [[ ${list1[@]} == ${list2[@] ]]; then
         echo 0
         break
             if [[  ${#list2[@]} == ${#list1[@]-1} && ${list1[@]} != ${list2[@]} ]];then
             echo ${list3[$i]}
         fi
     fi
done
done

3 个答案:

答案 0 :(得分:1)

您可以为此使用comm

int length
// ...
// ...
string substr
string str = "big long string with lots of text"
substr = str[0:length(str)-2]

导致

readarray -t unique < <( \
    comm -23 \
        <(printf '%s\n' "${list1[@]}" | sort) \
        <(printf '%s\n' "${list2[@]}" | sort) \
)

或者,为了获得所需的格式,

$ declare -p unique
declare -a unique=([0]="101" [1]="102" [2]="103" [3]="104")

$ printf '(%s)\n' "${unique[*]}" (101 102 103 104) 获取两个排序的文件(此处使用sort),并打印出第一个唯一的每一行; process substitution用于将列表输入comm -23

然后,readarray读取输出并将每一行放入comm数组的元素中。 (注意,这需要Bash。)


除其他外,您的尝试失败了,因为您试图在单个比较中比较多个元素:

unique

扩展到

[[ ${list1[@]} != ${list2[@]} ]]

而Bash抱怨期望使用二进制运算符而不是第二个元素[[ 10 20 30 40 50 60 90 100 101 102 103 104 != 10 20 30 40 50 60 70 80 90 100 ]]

答案 1 :(得分:0)

关联数组对此很方便:

list1=( 10 20 30 40 50 60 90 100 101 102 103 104)
list2=( 10 20 30 40 50 60 70 80 90 100 )
typeset -a onlyList1
typeset -A inList2
for elem in "${list2[@]}"; do inList2["$elem"]=1; done
for elem in "${list1[@]}"; do [[ -v inList2["$elem"] ]] || onlyList1+=("$elem"); done
typeset -p onlyList1
typeset -a onlyList1=(101 102 103 104)

或者类似地,从list1的所有开始,并删除list2中的内容:

typeset -A inList1
for elem in "${list1[@]}"; do inList1["$elem"]=1; done
for elem in "${list2[@]}"; do unset inList1["$elem"]; done
onlyList1=( "${!inList1[@]}" )

答案 2 :(得分:0)

也可以使用这种方法

if !moviePlayer.canBeginTrimming {
       // it returns false      
}

输出为

#!/bin/ksh

list1=( 10 20 30 40 50 60 90 100 101 102 103 104 )
list2=( 10 20 30 40 50 60 70 80 90 100 )

# Creating a temp array with index being the same as the values in list1

for i in ${list1[*]}; do
        list3[$i]=$i
done

# If value of list2 can be found in list3 forget this value

for j in ${list2[*]}; do
        if [[ $j -eq ${list3[$j]} ]]; then
                unset list3[$j]
        fi
done

# Print the remaining values

print ${list3[*]}

希望它会有所帮助

编辑

如果两个列表相同:

101 102 103 104