2012-10-15 35 views
2

工作时,我有两个文件我用下面的代码使用AWK阵列有两个文件

file1 
------------------------------- 
1  a  t  p  bbb 
2  b  c  f  aaa 
3  d  y  u  bbb 
2  b  c  f  aaa 
2  u  g  t  ccc 
2  b  j  h  ccc 

file2 
-------------------------------- 
1 11 bbb 
2 22 ccc 
3 33 aaa 
4 44 aaa 

合并他们基于密钥我用下面的代码

awk 'NR==FNR{a[$3]=$0;next;}{for(x in a){if(x==$5) print $1,$2,$3,$4,a[x]}; 

合并这两个文件基于密钥我问题是我如何将$ 2的file2保存在变量或数组中,并在[x]之后再次打印。
我期望的结果是:

1 a t p 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
3 d y u 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
2 u g t 2 22 ccc 22 
2 b j h 2 22 ccc 22 

正如你看到的第7个栏是我的代码合并的结果。我需要将最后一列([x]的第2个字段)添加到我的结果中。

重要:

我的下一个问题是,如果我有.awk文件,我怎么可以像使用(| column -t)一些bash脚本代码或发送结果到文件(awk... > result.txt)?我总是在命令提示符下使用这些代码。我可以在.awk文件的代码中使用它们吗?

回答

3

只要所有的file2添加到一个数组,并使用split抱着你想要的位:

awk 'FNR==NR { two[$0]++; next } { for (i in two) { split(i, one); if (one[3] == $NF) print $1,$2,$3,$4, i, one[2] } }' file2 file1 

结果:

1 a t p 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
3 d y u 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
2 u g t 2 22 ccc 22 
2 b j h 2 22 ccc 22 

关于你的最后一个问题;您还可以在awk中添加“管道”和“写入”。这里有一个管道来column -t为例:script.awk

内容:

FNR==NR { 
    two[$0]++ 
    next 
} 

{ 
    for (i in two) { 
     split(i, one) 
     if (one[3] == $NF) { 
      print $1,$2,$3,$4, i, one[2] | "column -t" 
     } 
    } 
} 

运行,如:awk -f script.awk file2 file1

编辑:

以下内容添加到您的shell脚本:

results=$(awk ' 

    FNR==NR { 
     two[$0]++ 
     next 
    } 

    { 
     for (i in two) { 
      split(i, one) 
      if (one[3] == $NF) { 
       print $1,$2,$3,$4, i, one[2] | "column -t" 
      } 
     } 
    } 
' $1 $2) 

echo "$results" 

运行,如:

./script.sh file2.txt file1.txt 

结果:

1 a t p 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
3 d y u 1 11 bbb 11 
2 b c f 3 33 aaa 33 
2 b c f 4 44 aaa 44 
2 u g t 2 22 ccc 22 
2 b j h 2 22 ccc 22 
+0

@steve ..亲爱的史蒂夫,当我在bash脚本中使用你的代码,它给了我错误..你能告诉我我的错误在哪里下面 '命令= $(AWK -f' FNR == NR { 2 [$ 0] ++ 下 } { 为(ⅰ两个){ 分裂(ⅰ,一个,FS) 如果(一个[3] == $ NF){ 打印$ 1,$ 2,$ 3,$ 4,I,一个[2] } } } “$ $的file1 file2的) 回波-e $命令|列-t – mohammad

+1

@mohammad:我发现了错误。你应该使用'$ 1'和'$ 2'(shell参数)而不是'$ file1'和'$ file2'。请参阅我的更新。固定。 – Steve

2

为了实现你所要求的,在处理第一个文件的整行之后保存第二个域,使用a[$3]=$0 OFS $2。对于你的第二个问题,awk有一个变量来分隔输出中的字段,它是OFS,为它分配一个制表符,并与它一起玩。您的脚本是这样的:

awk ' 
    BEGIN { OFS = "\t"; } 
    NR==FNR{ 
     a[$3]=$0 OFS $2; 
     next; 
    } 
    { 
     for(x in a){ 
      if(x==$5) print $1,$2,$3,$4,a[x] 
     } 
    } 
' file2 file1 

国债收益率:

1  a  t  p  1 11 bbb 11 
2  b  c  f  4 44 aaa 44 
3  d  y  u  1 11 bbb 11 
2  b  c  f  4 44 aaa 44 
2  u  g  t  2 22 ccc 22                                               
2  b  j  h  2 22 ccc 22 
+0

@Birei ..感谢亲爱的birei ..其实我想将它保存到变量数组或对未来arithmatic操作和计算每个字段的数量。例如我想说如果$ 2(的文件1)== 11然后... – mohammad

3

您当前的脚本是:

awk 'NR==FNR { a[$3]=$0; next } 
      { for (x in a) { if (x==$5) print $1,$2,$3,$4,a[x] } }' 

(实际上,原来是缺少了第二图案的第二紧密支柱/动作对)

看来你在处理012之前处理。

你不应该在第二个代码中需要循环。

awk 'NR==FNR { c1[$3] = $1; c2[$3] = $2; next } 
      { print $1, $2, $3, $4, c1[$5], c2[$5], $5, c2[$5] }' 

可以升级,以检查是否c1[$5]c2[$5]定义,想必跳过行,如果他们是:你可以通过使用在第一阶段的分裂,让你需要的值使生活更容易为自己不。

鉴于你的输入文件,输出是:

1 a t p 1 11 bbb 11 
2 b c f 4 44 aaa 44 
3 d y u 1 11 bbb 11 
2 b c f 4 44 aaa 44 
2 u g t 2 22 ccc 22 
2 b j h 2 22 ccc 22 

给予或采取柱间距,这是什么要求。列间距可以通过使用printf代替print,或设置OFS到标签是固定的,或...

c1c2符号列1和2是用于两列行。如果您需要更多,那么您应该使用二维数组符号:

awk 'NR==FNR { for (i = 1; i <= NF; i++) col[i,$3] = $i; next } 
      { print $1, $2, $3, $4, col[1,$5], col[2,$5], $5, col[2,$5] }' 

这会产生与以前相同的输出。