Awk - 如果密钥匹配,则组合来自2个文件的数据并打印到第3个文件

时间:2015-01-21 02:50:27

标签: awk

情境:

  • 我正在尝试编写一个Awk脚本。
  • 我有两个文件。 File1(制表符分隔),File2(字符串)。
  • 在File1中,我将第01行的Field4 + Field3 + Field2组合成一个 File2中字符串Field1的引用键。
  • 我能够匹配并提取信息,但不是一个好的格式

要求

  • 如果引用键匹配,我想将信息打印到File3.txt。我需要打印到File3,其中格式为
  • KEY MATCHED:来自File1的01-07行,后跟匹配的字符串 来自File2,前缀为77,依此类推。
  • KEY NOT MATCHED:如果键不匹配则将所有键都匹配 来自File2的不匹配记录,前缀为99。

脚本:

awk -F'\t' -v OFS'\t' 'FNR==NR{a[substr($0,1,8)]=$4$3$2}
     {if ($4$3$2 in a) printf ("77""\t"); else printf ("99""\t");print $0}' \
     File2.txt File1.txt > File3.txt

文件1:

01  89  68  5000
02  89  11
03  89  00
06  89  00
07  89  19  RT  0428
01  87  23  5100
02  87  11
04  87  9   02
03  87  00
06  87  00
07  87  11  RT  0428
01  83  23  4900
02  83  11
04  83  9   02
03  83  00
06  83  00
07  83  11  RT  0428

文件2:

50006889 CCARD /3010  /E     /C A87545457          /  //                ///11        ///

51002387 CCARD /3000  /E     /S N054896334IV          /  //                ///11        ///

51002390800666 CCARD /3000  /E     /S N0978898IV          /  //                ///11        ///

文件3: 当前输出

99  50006889 CCARD /3010  /E     /C A87545457          /  //                ///11        ///
99
99  51002387 CCARD /3000  /E     /S N054896334IV          /  //                ///11        ///
99
99  51002390800666 CCARD /3000  /E     /S N0978898IV          /  //                ///11        ///
77  01  89  68  5000
99  02  89  11
99  03  89  00
99  06  89  00
99  07  89  19  RT
77  01  87  23  5100
99  02  87  11
99  04  87  9   02
99  03  87  00
99  06  87  00
99  07  87  11  RT  0428    
99  01  83  23  4900
99  83  11
99  83  9   02
99  83  00
99  83  00
99  83  11  RT  0428

期望输出:

01  89  68  5000
02  89  11
03  89  00
06  89  00
07  89  19  RT  0428
77  50006889 CCARD /3010  /E     /C A87545457          /  //                ///11        ///

01  87  23  5100
02  87  11
04  87  9   02
03  87  00
06  87  00
07  87  11  RT  0428
77  51002387 CCARD /3000  /E     /S N054896334IV          /  //                ///11        ///

99  51002390800666 CCARD /3000  /E     /S N0978898IV          /  //                ///11        ///

实际上对于77和99行,我需要整个字符串,但77和99仅在匹配键的开头。目前,如果字符串很长并且继续到第二行,则脚本也将77和99放在第二行的前面 我期待将77和99放在匹配的代码前面。

例如,以下是Jonathan修正后的awk代码的输出:

$ awk -f awk.script File2.txt File1.txt

        01  89  68  5000
        02  89  11
        03  89  00
        06  89  00
        07  89  19  RT  0428
        77  50006889 CCARD /3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ///
        01  87  23  5100
        02  87  11
        04  87  9   02
        03  87  00
        06  87  00
        07  87  11  RT  0428
        77  51002387 CCARD /3000  /E     /S N054896334IV          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //      
77          ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ////3010  /E     /C A87545457          /  //                ///11        ///
        01  83  23  4900
        02  83  11
        04  83  9   02
        03  83  00
        06  83  00
        07  83  11  RT  0428
        99  51002390800666 CCARD /3000  /E     /S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV    
    99        /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///////S N0978898IV          /  //                ///11        ////S N09
    99  78898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ////S N0978898IV          /  //                ///11        ///
        $

1 个答案:

答案 0 :(得分:1)

在阅读File2.txt之前,您已正确阅读File1.txt。但是,您需要忽略File2.txt中的空白行。

FNR == NR && ! /^[[:space:]]*$/ { key = substr($1, 1, 8); a[key] = $0; next }

这使用第一个字段的前8个字符作为键,整行作为值。 next确保不会以其他方式处理这些行。

下一部分是繁琐的。您需要在01中找到$1的行,然后从中构建一个键。当您下次获得01行时,您需要打印出来自a的77前缀行(并从a删除该条目)。

最后,您需要从a打印77前缀的行(并从a删除条目)。然后,您需要处理a中留下的任何条目,并为它们提供99前缀。

$1 == "01" { if (code != 0)
             {
                 if (code in a)
                 {
                     printf("77\t%s\n", a[code])
                     delete a[code]
                 }
             }
             code = $4$3$2
           }
{ print }
END {
         if (code in a)
         {
             printf("77\t%s\n", a[code])
             delete a[code]
         }
         for (code in a)
             printf("99\t%s\n", a[code])
    }

显然,你可以使用比我刚才更少的空白区域,尽管你可能还需要添加一些分号。出于测试目的,我将上面的代码放入文件awk.script并运行:

$ awk -f awk.script File2.txt File1.txt
01  89  68  5000
02  89  11
03  89  00
06  89  00
07  89  19  RT  0428
77  50006889 CCARD /3010  /E     /C A87545457          /  //                ///11        ///
01  87  23  5100
02  87  11
04  87  9   02
03  87  00
06  87  00
07  87  11  RT  0428
77  51002387 CCARD /3000  /E     /S N054896334IV          /  //                ///11        ///
01  83  23  4900
02  83  11
04  83  9   02
03  83  00
06  83  00
07  83  11  RT  0428
99  51002390800666 CCARD /3000  /E     /S N0978898IV          /  //                ///11        ///
$

这看起来与你想要的相似。如果要在上一个输出块之后留空行,请在打印77前缀行的printf("\n")块之后添加if。如果您喜欢I / O重定向,可以将其写入File3.txt。您可以将脚本嵌入单引号中,并将其添加到命令行以代替-f awk.script。如果你愿意的话,你可以将整个剧本压缩到一条巨大的线上 - 但请不要;这个程序的名称是awk,而不是apl