如何使用AWK打印?

时间:2010-09-13 12:48:42

标签: awk

我有一个看起来像这样的文件:

1 543423 34354 
2 5654656 3423 xyz_1378,xyz_1379
3 4645656 34234354 xyz_1384,xyz_1385
4 5654 78678 xyz_1390,xyz_1391,xyz_1392
5 54654 76867 xyz_1411,xyz_1412,xyz_1413
6 54654 8678 
7 56546 67867 xyz_1711
8 678 7867 
9 76867 7876 xyz_2940
10 6786 678678 xyz_3101,xyz_3102,xyz_3103,xyz_3104,xyz_3105,xyz_3106,xyz_3107
11 67867 78678 

注意它包含4个字段,空格分隔。最后一个(第四个)字段可能为空,并且可能包含以逗号分隔的多个值。

我想打印最后一行的所有值,每行一个。我怎么能这样做(最好用awk)?

更新: 我需要批量处理许多文件(获取所有文件的连接输出)。

这有效:

for x in *; do awk '{print $4}' $x/filename | awk --field-separator="," '{if ($0 != "") {for (i=1; i<NF+1; i++) print $i}}'; done;

并返回类似

的内容
xyz_1378
xyz_1221
xyz_97
xyz_132523
xyz_242

我现在唯一缺少的是,我希望上面的每一行都以一个额外的字段开头 - $ x(来自for循环的字段)。

我尝试将print $i更改为print $x,$i" but x`似乎在此范围内无法正确识别。有什么想法吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

使用awk的-v选项将变量传递给awk脚本,而不是依赖于shell的替换。此外,您只需要一次调用awk

for dir in *; do 
    awk -v "dir=$dir" '
        NF==4 {
            n = split($4, a, ",")
            for (i=1; i<=n; i++) {print dir "\t" a[i]}
        }
    ' "$dir/filename"
done

或者,如果你不介意看“dir / filename”:

awk '
    NF==4 {
        n = split($4, a, ",")
        for (i=1; i<=n; i++) {print FILENAME "\t" a[i]}
    }
' */filename

如果你有大量的目录,你的shell可能会在扩展“* / filename”时窒息,所以使用find和xargs:

find . -type f -name filename -print0 | xargs -0 awk '...'

(-print0 / -0选项需要GNU find / xargs)

答案 1 :(得分:0)

您可以将命令中的一个语句更改为

awk '{print FILENAME "," $4}' $x

然后处理此输出。

FILENAME是用于获取正在处理的文件的文件名的内部awk变量。

答案 2 :(得分:-1)

使用NF>=4作为条件,以查看字段中是否有任何内容。然后split($4,a,/,/)将为您提供包含所有值的数组a。把它放到一个大的结果数组中:

NF>=4 {
    n = split($4, a, /,/);
    for( i=1; i<=n; i++ ) {
        result[a[i]] = 0;
    }
}

并在最后打印:

END {
    for( val in result ) {
        print val;
    }
}

如果您希望对其进行排序,请通过管道sort(1)

过滤输出