【问题标题】:use awk to match rows for each column使用 awk 匹配每一列的行
【发布时间】:2015-12-15 17:41:53
【问题描述】:

如何使用 awk 为每列查找与第 2 行匹配的值?

我想获取一个选项卡限制文件,如果第 2 行下方的任何行与第 2 行中的内容匹配,则对于每一列,使用“匹配”打印字段。

转换此制表符分隔文件:

header1 | header2 | header3
1       | 1       | B
--------+---------+----------
3       | 1       | A
2       | A       | B
1       | B       | 1

到这里:

header1 | header2 | header3
1       | 1       | B
--------+---------+----------
3       | 1 match | A
2       | A       | B match
1 match | B       | 1

【问题讨论】:

  • 您的数据实际上是这样的吗,--+--,还是每个字段之间只有制表符? @anubhava 因为它不是1,我猜。
  • 第 1 列中所需的匹配是 1。第 2 列所需的匹配又是 1,第 3 列所需的匹配是 B。每一列都需要独立取。
  • 数据仅以制表符分隔。我试图通过添加--+-- 来说明这一点,但事实并非如此。感谢您的评论。

标签: bash awk


【解决方案1】:

我会选择这样的:

$ cat file
header1 header2 header3
1       1       B
3       1       A
2       A       B
1       B       1
$ awk -v OFS='\t' 'NR == 2 { for (i=1; i<=NF; ++i) a[i] = $i }
    NR > 2 { for(i=1;i<=NF;++i) if ($i == a[i]) $i = $i " match" }1' file
header1 header2 header3
1       1       B
3       1 match A
2       A       B match
1 match B       1

在第二行,用每个字段的内容填充数组a。在随后的行中,当它们与数组中的相应值匹配时添加“匹配”。末尾的1 是一个常见的速记,导致每行都被打印。将输出字段分隔符OFS 设置为制表符会保留数据的格式。

【讨论】:

    【解决方案2】:

    迂腐,GNU Awk 4.1.1:

    awk -f so.awk so.txt
    header1 header2 header3
    1       1       B
    3       1*      A
    2       A       B*
    1*      B       1
    

    so.awk:

    {
        if(1 == NR) {
            print $0;
        } else if(2 == NR) {
            for(i = 1; i <= NF; i++) {
                answers[i]=$i;
            }
            print $0;
        } else {
            for(i = 1; i <= NF; i++) {
                field = $i;
                if(answers[i]==$i) {
                    field = field "*" # a match
                }
                printf("%s\t",field);
            }
            printf("%s", RS);
        }
    }
    

    so.txt 作为制表符分隔的数据文件:

    header1 header2 header3
    1       1       B
    3       1       A
    2       A       B
    1       B       1
    

    这不是家庭作业,对吧...?

    【讨论】:

    • 酷——不客气。如果您对此答案感到满意,请不要忘记投票并通过单击复选标记来选择它。 ;-)
    猜你喜欢
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2017-12-16
    相关资源
    最近更新 更多