在bash中2个数组之间查找对的最有效方法

时间:2018-12-20 20:43:35

标签: bash shell sh

我有2个大型数组,其中存储了哈希值。我正在尝试找到验证在array_b中也找到array_a中所有哈希值的最佳方法。到目前为止,我最好的是

  1. 将哈希文件导入数组
  2. 对每个数组排序
  3. 用于遍历array_a
  4. 在array_a的for循环内,另做一次寻找array_b(似乎效率低下)。
  5. 如果在array_b中发现未设置的值
  6. 将“找到的”值设置为1并中断循环
  7. 如果array_a没有与文件匹配的输出。

我有需要验证的大图像已上传到网站,并且哈希值匹配。我已经从原始文件创建了一个文件,并抓取了网站文件,以创建第二个哈希值列表。尽量保持这种状态,因此仅使用典型的bash功能。

#!/bin/bash

array_a=($(< original_sha_values.txt))
array_b=($(< sha_values_after_downloaded.txt))

# Sort to speed up.
IFS=$'\n' array_a_sorted=($(sort <<<"${array_a[*]}"))
unset IFS
IFS=$'\n' array_b_sorted=($(sort <<<"${array_b[*]}"))
unset IFS

for item1 in "${array_a_sorted[@]}" ; do
  found=0

  for item2 in "${!array_b_sorted[@]}" ; do
    if [[ $item1 == ${array_b_sorted[$item2]} ]]; then
      unset 'array_b_sorted[item2]'
      found=1
      break
    fi
  done

  if [[ $found == 0 ]]; then
    echo "$item1" >> hash_is_missing_a_match.log
  fi
done

排序以加快速度

IFS=$'\n' array_a_sorted=($(sort <<<"${array_a[*]}"))
unset IFS
IFS=$'\n' array_b_sorted=($(sort <<<"${array_b[*]}"))
unset IFS

这真的是最好的方法吗?

for item1 in "${array_a_sorted[@]}" ; do
 ...
  for item2 in "${!array_b_sorted[@]}" ; do
    if ...
       unset 'array_b_sorted[item2]'
       break

两个阵列都有12,000行的64位散列,需要20多分钟才能进行比较。有没有提高速度的方法?

2 个答案:

答案 0 :(得分:3)

您正在努力工作。

如果任务是:在file1中找到条目,而不在file2中找到条目。这是一种较短的方法

$ comm -23 <(sort f1) <(sort f2)

答案 1 :(得分:1)

如果您只想完成它而不用担心优化bash代码,我认为karakfa的答案可能是最好的方法。

但是,如果您仍然想在bash中进行操作,并且愿意使用某些bash特定的功能,则可以使用关联数组而不是两个来节省大量时间常规数组:

# Read the original hash values into a bash associative array

declare -A original_hashes=()
while read hash; do
  original_hashes["$hash"]=1
done < original_sha_values.txt

# Then read the downloaded values and check each one to see if it exists
# in the associative array. Lookup time *should* be O(1)

while read hash; do
  if [[ -z "${original_hashes["$hash"]+x}" ]]; then
    echo "$hash" >> hash_is_missing_a_match.log
  fi
done < sha_values_after_downloaded.txt

这应该比使用常规数组的嵌套循环实现快得多。另外,我不需要任何排序,并且假设bash将关联数组实现为哈希表,则关联数组上的所有插入和查找都应为O(1)。我找不到任何有力的证据来支持这一点,所以请带一点盐。无论哪种方式,它都应该比嵌套循环方法要快。

如果要对输出进行排序,则只需将最后一行更改为:

done < <(sort sha_values_after_downloaded.txt)

在这种情况下,您仍然只需要排序一个文件,而不是两个。