【问题标题】:search duplicate element array搜索重复元素数组
【发布时间】:2014-03-30 02:22:02
【问题描述】:

这件作品:

arr[0]="XX1 1"
arr[1]="XX2 2" 
arr[2]="XX3 3"
arr[3]="XX4 4"
arr[4]="XX5 5"
arr[5]="XX1 1"
arr[6]="XX7 7"
arr[7]="XX8 8"

duplicate() { printf '%s\n' "${arr[@]}" | sort -cu |& awk -F: '{ print $5 }'; }

duplicate_match=$(duplicate)

echo "array: ${arr[@]}"

# echo "duplicate: $duplicate_match"

[[ ! $duplicate_match ]] || { echo "Found duplicate:$duplicate_match"; exit 0; }

echo "no duplicate"

使用相同的代码,这个不起作用,为什么?

arr[0]="XX"
arr[1]="wXyz" 
arr[2]="ABC"
arr[3]="XX"

【问题讨论】:

  • 您的代码实际上不起作用,因为sort -cu 在输入尚未排序时失败;它在第一个数据集中找到的重复项恰好是第一个无序出现的项目。
  • 管道符号组合仅在c-shell中有效,在bash中无效
  • @chepner 谢谢,我将搜索如何在正确的位置对我的数组进行排序。
  • @thom |& 在版本 4 中也被添加到 bash
  • @chepner 谢谢,我的立场是正确的。管道符号确实有效。

标签: arrays bash duplicates


【解决方案1】:

要检查重复,此代码要简单得多,并且适用于两种情况:

uniqueNum=$(printf '%s\n' "${arr[@]}"|awk '!($0 in seen){seen[$0];c++} END {print c}')

(( uniqueNum != ${#arr[@]} )) && echo "Found duplicates"

编辑:要打印重复项,请使用此 awk:

printf '%s\n' "${arr[@]}"|awk '!($0 in seen){seen[$0];next} 1'

如果一行还不是seen 数组的一部分,则Awk 命令将存储在数组seen 中,然后移至下一行。 1 最后只打印那些重复的行。

【讨论】:

  • 感谢 Anubhava,我需要研究您的代码才能完全理解它,请问如何在 echo 中返回重复的元素?也有人可以更正我的代码吗?我从两个小时开始就一直在这样做,并且在不理解我的情况下完成使用另一个代码令人沮丧:(
  • 如果您想了解代码失败的原因,请参阅下面 chepner 的回答。
  • 我的回答中也添加了一些解释。
  • @Neeraj:试试这个:printf '%s\n' "${arr[@]}" | awk '!seen[$0]++ {} END {print length(seen)}'
【解决方案2】:

这里有点愚蠢的解决方案。我只是想看看是否可以在没有显式管道的情况下在单个命令中执行此操作。 (我认为对于非常大的数组/数组元素,explicit pipes might actually be more efficient。)

请注意,这是对是否存在重复数组元素的测试,并且不会输出重复项本身,尽管 awk 命令本身会执行此操作。另请注意,如果您很不幸地拥有包含空格的数组元素,则以下内容将不会按照描述进行计算。

[[ $( awk -v RS=" " ' a[$0]++ ' <<< "${arr[@]} " ) ]] && echo "dups found"

解释:

awk -v RS=" "

  • 对每个输入记录执行后续awk 命令,空格作为记录分隔符。基本上,这将使awk 将每个数组元素视为单独的“行”。

' a[$0]++ '

  • awk 命令做两件事:

    • 返回数组a 中键$0 处的值。如果这大于 0,则打印该行。对比awk ' { $1=$2 } 1 '

    • 将数组a中键$0的值加1。

&lt;&lt;&lt; "${arr[@]} "

  • 作为awk 命令的输入,使用打印arr 中的每个元素时创建的字符串作为单独的单词,即用空格分隔在末尾加上一个额外的空格强>。

  • }" 之间的空格实际上非常重要,因为没有它,最终的数组元素不会在其后有空格,并且因此,awk不会将其视为不同的“记录”。

[[ $( ... ) ]]

  • 如果包含 awk 命令给出任何输出,则测试评估为 0,即 TRUE。

【讨论】:

    猜你喜欢
    • 2015-04-18
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 2012-09-01
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多