awk打印数组的单个元素

时间:2012-01-20 04:31:45

标签: awk

这应该是非常容易的。我只想打印一个数组元素。但是,我从print arr[1]这样的命令得到的只是一个空行。

这是我的整个bash脚本:

#!/bin/bash
find -X $1 -type f | 
xargs md5 | 
awk '

NF == 4 {
     md5[$4]++;
     files[$2]++;
}

END {
    for (i = 1; i <= NF; i++)
    for (j = i + 1; j <= NF; j++)
        if (md5[i] == md5[j]) {
            print "These are duplicates: "
            print files[j+1]
            print files[i]
        }

'

exit 0

这是一个非常简单的重复文件查找器。有问题的部分位于awk中的END {}语句中。

这只是给了我一堆“这些是重复的:”后面带有空行。我知道这些信息是可用的,因为我将它添加到END {}:for (x in arr); print x并且它完美地打印出arr中的每个元素,如预期的那样。

我必须做一些非常愚蠢的事情。

3 个答案:

答案 0 :(得分:2)

您目前正在做的是将要保存的值分配为两个数组的索引,这似乎是awk中的代码示例所常见的。但是,这通常与for (x in y)语法一起使用。要修复您的代码,想到修复您正在做的事情的方法是修改您的awk位,如下所示:

BEGIN {
    md5idx = 0;
    filesidx = 0;
}

然后改变:

NF == 4 {
    md5[md5idx++] = $4;
    files[filesidx++] = $2;
}

我想应该这样做,但我没有测试过它。

答案 1 :(得分:2)

您也可以使用包含NR的{​​{1}}作为索引,而不是使用变量来将字段值存储到数组中。

line number

然后在NF == 4 { md5[NR]=$4; files[NR]=$2; } 部分中,您可以使用END之类的内容。由于在for (i=1;i<=NR;i++}中您始终将END statement的值作为最后一个行号,因此您无需使用任意数字,甚至NR length function awk找到数组的长度。

答案 2 :(得分:1)

我花了一段时间才找到标准md5而不是我自己的家酿版本,但MacOS X 10.7.2版本的示例输出是:

$ /sbin/md5 $(which -a md5)
MD5 (./md5) = 57f49e1c53ca7875fe63a33958ab0b0b
MD5 (/Users/jleffler/bin/md5) = 57f49e1c53ca7875fe63a33958ab0b0b
MD5 (/sbin/md5) = dd00b1dc4dd11c8443a70b5d33e0cade
$

假设md5的输出是第4列中的散列,第2列中的文件名,名称周围的括号无关紧要,并且还假设名称不包含任何空格(因为文件名会弄乱列编号),那么你可能想要这样的东西:

#!/bin/bash
find -X "${@:-'.'}" -type f | 
xargs /sbin/md5 | 
awk '
NF == 4 {
     if (file[$4] != "") printf "Duplicate: MD5 %s - %s & %s\n", $4, file[$4], $2;
     else file[$4] = $2;
}'

exit 0

示例输出:

Duplicate: MD5 57f49e1c53ca7875fe63a33958ab0b0b - (./md5) & (/Users/jleffler/bin/md5)

这标识了重复的MD5值。如果给定MD5哈希的(关联)数组file中没有条目,则使用文件名创建条目。如果有条目,则打印MD5值和两个文件名;你可以讨论这种格式,它可能会更好地分布在三条线上而不是局限于一条线上。

"${@:-'.'}"符号表示'如果有的话,使用命令行参数;否则,使用.(当前目录)'。这似乎比使用第一个参数(仅)更有用,如果没有提供参数则失败。