【问题标题】:How to print this using AWK?如何使用 AWK 打印?
【发布时间】:2015-11-02 21:09:15
【问题描述】:

我有一个如下所示的文件:

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" butx` 在此范围内似乎无法正确识别。有什么想法吗?

谢谢!

【问题讨论】:

  • 当您说“我想打印最后一行的所有值,每行一个”。你的意思是“最后一栏”吗?

标签: awk


【解决方案1】:

使用 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

或者,如果您不介意看到“目录/文件名”:

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)

【讨论】:

  • 次要评论:如果顺序不重要,可以使用更简单的for (i in a) 而不是for (i=1; i&lt;=n; i++)
【解决方案2】:

也许您可以将命令中的语句之一更改为

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

然后处理这个的输出。

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

【讨论】:

    【解决方案3】:

    使用NF&gt;=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) 管道过滤输出

    【讨论】:

    • 我尝试过测试,但这会打印 1 到 7,每个都在一行上。我是不是在什么地方弄错了?
    • -1:这似乎是打印最后一行值的最后一位数字,巧合的是,从 1 到 7。
    • 抱歉,我忘了for(x in y) 不适用于数组。固定。
    • 如果$4 计算结果为数字零,if($4) 也会返回 false。我们不知道实际数据,所以据我们所知,这是可能的。 if(length($4)) 可能是更安全的选择。
    • @ghoti:我现在像其他答案一样使用NF&gt;=4
    猜你喜欢
    • 2015-04-15
    • 2021-08-07
    • 2020-03-01
    • 2021-08-19
    • 2023-03-12
    • 1970-01-01
    • 2011-05-17
    • 2015-11-04
    • 1970-01-01
    相关资源
    最近更新 更多