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

使用shell脚本比较两个不同的数组,shell,sh,ksh,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 ) 我的要求是比较这两个数组的顺序,以便它只显示列表1中的(101 102 103 104)。它不应包括出现在list2中但不出现在list1中的值70和80 这没有帮助,因为它包括所有内容: echo "${list1[@]}" "${li

如何比较两个数组并在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 )
我的要求是比较这两个数组的顺序,以便它只显示
列表1中的
(101 102 103 104)
。它不应包括出现在
list2
中但不出现在
list1
中的值
70
80

这没有帮助,因为它包括所有内容:

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
list1=(10203040506070100101010104)
列表2=(10203005060708090100)
对于((i=0;i您可以使用:

readarray -t unique < <( \
    comm -23 \
        <(printf '%s\n' "${list1[@]}" | sort) \
        <(printf '%s\n' "${list2[@]}" | sort) \
)
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
或者,要获得所需的格式

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

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


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

[[ ${list1[@]} != ${list2[@]} ]]
扩展到

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

关联数组非常方便:

readarray -t unique < <( \
    comm -23 \
        <(printf '%s\n' "${list1[@]}" | sort) \
        <(printf '%s\n' "${list2[@]}" | sort) \
)
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
或者类似地,从所有列表1开始,删除列表2中的内容:

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

也可以使用这种方法

#!/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
希望能有所帮助

编辑 如果两个列表相同:

# Print the remaining values

if [[ ${#list3[*]} -eq 0 ]]; then
        print "No differences between the list"
else
        print ${list3[*]}
fi

谢谢。这对我来说非常有效。但是当我试图处理异常时,它没有很好的响应。如果[-n${list3}]];那么real_val=$(echo 0)否则real_val=$(echo“${list3[@]}”)fi echo$real_val什么样的异常?-z也不起作用。尝试了list3[@]或list3[*]在if子句中。有什么建议可以处理吗?假设在list1和list2中两个数组都包含相同的值,那么数组输出将为null。因此,我试图做的是-如果数组返回null,它将显示0。再次感谢..其工作..看起来算术比较产生了实际结果。感谢您的输入,但这在我的环境中不起作用。