2

我在 Internet 上找到了以下 AWK 程序,并对其稍作调整以查看第 2 列:

{ a[$2,NR]=$0; c[$2]++ }
END {
    for( k in a ) {

       split(k,b,SUBSEP)

       t=c[b[1]] # added this bit to capture count

       if( b[1] in c && t>1 ) { # added && t>1 only print if count more than 1
         print RS "TIMES  ID" RS c[b[1]] "  " b[1] RS
         delete c[b[1]]
       }

       for(i=1;i<=NR;i++) if( a[b[1],i] ) {
          if(t>1){print a[b[1],i]} # added if(t>1) only print lines if count more than 1
          delete a[b[1],i]
       }
    }
}

给定以下文件:

abc,2,3
def,3,4
ghi,2,3
jkl,5,9
mno,3,2

运行命令时输出如下:

Command: awk -F, -f find_duplicates.awk duplicates

Output:
TIMES  ID
2  2

abc,2,3
ghi,2,3

TIMES  ID
2  3

def,3,4
mno,3,2

这可以。

我想了解 AWK 程序中发生了什么。

我知道第一行是将每一行加载到一个多维数组中?所以文件的第一行将是a['2','1']='abc,2,3'等等。

但是,我对做什么c[$2]++以及split(k,b,SUBSEP)??

如果有人可以逐行解释此 AWK 程序中发生的事情,将不胜感激。

谢谢。

4

1 回答 1

2

增量运算符只是将引用变量的值加一。所以c[$2]++取值c[$2]并加一。如果$2isac["a"]was 3 之前,它的值将4在此之后。因此,请c跟踪$2您看到的每个值的数量。

for (k in a)循环a. 如果$2第一行的"a"值为 ,则 的第一个值为k"a","1"(其中 1 为行号)。下一次,它将是$2第二行的值和行号 2 等的组合。

将从中的复合值split(k,b,SUBSEP)创建一个新数组,即基本上重建进入的复合键的部分。现在 in 的值将是创建相应值 in 时的值,而 in 的值将是相应的行号。bkab[1]$2ab[2]

最后的循环有点低效;它遍历所有可能的行号,然后如果该 ID 和行号的条目不存在,则立即跳到下一个。因为它在外部循环内运行,for (k in a)所以如果您有大量输入,它将重复很多次(它将遍历每个输入行的所有输入行号)。以增加一些额外的内存为代价,仅以增量方式构建最终输出,然后在循环完所有 之后将其全部打印出来,这会更有效,a此时您已经处理了所有输入行。也许是这样的:

END {
    for (k in a) {
        split (k,b,SUBSEP)
        if (c[b[1]] > 1) {
            if (! o[b[1]]) o[b[1]] = c[b[1]] "  " b[1] RS
            o[b[1]] = o[b[1]] RS a[k]
        }
        delete a[k]
    }
    for (q in o) print o[q] RS
}

更新:删除过早删除c[b[1]].

于 2012-09-10T20:40:35.940 回答