如何添加“uniq -c”结果并在循环中连续覆盖?

如何添加“uniq -c”结果并在循环中连续覆盖?

我正在编写一个 shell 脚本,我想将唯一值的结果及其计数一次合并到一个文件中。例如,如果我正在从下面的两个文件中读取数据(第一列中的数字是唯一计数):

第一个循环读取数据

3 Dog   
1 Cat   
5 Horse

Data Read in Second Loop

1 Dog  
3 Cat  
1 Horse  
2 Goat 

我希望将第二个和第一个文件合并,以便将我的“计数文件”覆盖为:

第二次循环完成后的结果文件

4 Dog  
4 Cat  
6 Horse  
2 Goat 

我试图完成此任务,因为数据集很大,我宁愿读取和删除文件而不是下载(或者将cat文件放在一起并uniq -c在最后找到,因为文件会很长)。有没有办法做到这一点?谢谢你!

答案1

此方法用于awk对临时文件tallytmp和名为简单的运行计数进行求和tally。我将sort第二个字段上的两个计数文件放在一起 ( -k2)

它需要一个空白文件tally开始,所以touch tally,然后对于每次迭代:

uniq -c file > tallytmp
sort -k2 tally tallytmp \
  |awk '{
          if($2==prev){
            tot+=$1
          }else{
            print tot,prev;
            tot=$1;pc=$1;prev=$2
          }
        }END{
          print tot,prev
        }' > tallyresult
cp tallyresult tally

(继续,将awk脚本放在一行中。)

从逻辑上讲,我应该能够将sort|awk管道直接重定向到tally,但sort仍在使用它,所以它会破坏它;因此tallyresult在将其复制到我们的结果文件之前,需要第二个临时文件tally

所提供的两次迭代的输出实际上是:

[blank line]
4 Cat
4 Dog
2 Goat
6 Horse

顺序是根据字段 #2 的顺序混合的,但它工作正常。我能够使用它运行一些迭代。

答案2

有人刚刚对我之前的答案投了赞成票,所以我当然必须发明一个新的解决方案!这个更好一点,有两个原因:

  1. 它是纯粹的bash,使用哈希表而不是依赖awk
  2. 你不会看到垃圾空白行
  3. 可以添加任意数量的文件tally(三个原因)
  4. 文件tally可能开始为空(四个原因)
  5. 它不需要临时文件(“我没想到”等)

将以下内容另存为tally.sh

#!/bin/bash
# define the associative array tally_table
declare -A tally_table
while read line ; do
    k=($line)
    [ -n "${k[1]}" ] && (( tot[${k[1]}] += ${k[0]} ))
done <<HERE
$(cat tally $@)
HERE
for i in "${!tally[@]}"; do
    echo "${tally[$i]} $i"
done > tally
cat tally

尝试删除tally并创建一个新的报告文件,命名file为以下几行:

1 Horse
3 Monkey

然后将其输入:

$ ./tally.sh file
3 Monkey
1 Horse

现在创建另一个报告,名称newfile为几行:

5 Horse
2 Pig

并喂它:

$ ./tally.sh newfile
3 Monkey
6 Horse
2 Pig

Horse条目已正确递增。当然,就像以前一样,顺序不一致。 (我不知道你会如何排序狗猫马山羊订购,或属于Monkey其中的位置。)

相关内容