【问题标题】:compare two fields from two different files using awk使用 awk 比较来自两个不同文件的两个字段
【发布时间】:2019-08-24 11:23:42
【问题描述】:

我有两个文件,我想比较某些字段并生成输出

我也有一个变量

echo ${CURR_SNAP}
123

文件1

DOMAIN1|USER1|LE1|ORG1|ACCES1|RSCTYPE1|RSCNAME1
DOMAIN2|USER2|LE2|ORG2|ACCES2|RSCTYPE2|RSCNAME2
DOMAIN3|USER3|LE3|ORG3|ACCES3|RSCTYPE3|RSCNAME3
DOMAIN4|USER4|LE4|ORG4|ACCES4|RSCTYPE4|RSCNAME4

文件2

ORG1|PRGPATH1
ORG3|PRGPATH3
ORG5|PRGPATH5
ORG6|PRGPATH6
ORG7|PRGPATH7

我期望的输出如下,其中最后一列是 CURR_SNAP 值,并且匹配将是 File1 的第 4 列应该与 File2 的第 1 列匹配

DOMAIN1|USER1|LE1|ORG1|ACCES1|RSCTYPE1|123
DOMAIN3|USER3|LE3|ORG3|ACCES3|RSCTYPE3|123

我尝试了下面的代码片段,但看起来我做得不对

awk -v CURRSNAP="${CURR_SNAP}" '{FS="|"} NR==FNR {x[$0];next} {if(x[$1]==$4) print $1"|"$2"|"$3"|"$4"|"$5"|"$6"|"CURRSNAP}' File2 File1

【问题讨论】:

标签: unix awk


【解决方案1】:

与awk:

#! /bin/bash

CURR_SNAP="123"

awk -F'|' -v OFS='|' -v curr_snap="$CURR_SNAP" '{
    if (FNR == NR)
    {
        # this stores the ORG* as an index
        # here you can store other values if needed
        orgs_arr[$1]=1 
    }
    else if (orgs_arr[$4] == 1)
    {
        # overwrite $7 to contain CURR_SNAP value
        $7=curr_snap
        print
    }
}' file2 file1

正如您预期的输出,您没有输出RSCNAME*,所以我用$CURR_SNAP 覆盖了$7(这是RSCNAME* 的列)。如果您还想显示RSCNAME* 列,请删除$7=curr_snap 并将print 语句更改为print $0, curr_snap。

【讨论】:

    【解决方案2】:

    我根本不会使用awk。这就是join(1) 的含义(加上sed 附加额外的列:

    $ join -14 -21 -t'|' -o 1.1,1.2,1.3,1.4,1.5,1.6 File1 File2 | sed "s/$/|${CURR_SNAP}/"
    DOMAIN1|USER1|LE1|ORG1|ACCES1|RSCTYPE1|123
    DOMAIN3|USER3|LE3|ORG3|ACCES3|RSCTYPE3|123
    

    它确实需要根据公共字段对文件进行排序,就像您的示例一样。

    【讨论】:

    • 两个文件的实际大小都以 GB 为单位,当我尝试该命令时,它会抛出错误“join: file1 is not in sorted order”
    • @KoushikChandra 就像我说的,加入确实需要对文件进行排序。如果您不是,请考虑编辑您的示例以反映这一点。如果使用 bash、zsh 等,对它们进行排序的一种简单方法是 join other args <(sort -t'|' -k4,4 File1) <(sort -t'|' -k1,1 File2)。如果这是要经常运行的东西,或者提前对它们进行排序。
    【解决方案3】:

    您可以通过两个规则使用awk 来执行此操作。对于第一个文件(NR==FNR),只需使用字符串连接附加字段1 - (NF-1),将连接结果分配给由$4 索引的数组。然后对于规则二中的第二个文件(其中NR>FNR)测试array[$1] 是否有内容,如果有,则输出数组并附加"|"CURR_SNAP(在下面的示例中,CURR_SNAP 缩短为c,数组为a),例如

    CURR_SNAP=123
    
    awk -F'|' -v c="$CURR_SNAP" '
        NR==FNR {
            for (i=1;i<NF;i++)
                a[$4]=i>1?a[$4]"|"$i:a[$4]$1
        }
        NR>FNR {
            if(a[$1])
                print a[$1]"|"c
        }
    ' file1 file2
    

    使用/输出示例

    将文件名设置为与您的匹配后,您可以简单地在控制台中复制/鼠标中键粘贴进行测试,例如

    $ awk -F'|' -v c="$CURR_SNAP" '
    >     NR==FNR {
    >         for (i=1;i<NF;i++)
    >             a[$4]=i>1?a[$4]"|"$i:a[$4]$1
    >     }
    >     NR>FNR {
    >         if(a[$1])
    >             print a[$1]"|"c
    >     }
    > ' file1 file2
    DOMAIN1|USER1|LE1|ORG1|ACCES1|RSCTYPE1|123
    DOMAIN3|USER3|LE3|ORG3|ACCES3|RSCTYPE3|123
    

    检查一下,如果您还有其他问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 2014-12-25
      • 1970-01-01
      • 2015-10-22
      • 2023-04-11
      • 2017-01-31
      • 1970-01-01
      • 2018-03-04
      • 1970-01-01
      相关资源
      最近更新 更多