将两个awk acripts的输出合并为一个文件

时间:2016-12-15 08:28:34

标签: bash awk

我有一个包含150多列和50M行的大型输入文件,其示例如下所示:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1

我有一个bash shell脚本:

function awkScript() {
awk -F, -v cols="$1" -v hdr="$2" '
   BEGIN {OFS=FS}
   NR==1 {n=split(cols,cn); 
          for(i=1;i<=NF;i++) 
            for(j=1;j<=n;j++) 
              if($i==cn[j]) c[++k]=i; 
          $(NF+1)=hdr}
   NR >1 {v1=$c[1]; v2=$c[2]; v3=$c[3]
          if(!v2 && !v3) $(NF+1) = v1?10:0
          else $(NF+1) = v3?(v1-v3)/v3:0 + v2?(v1-v2)/v2:0}1' "$3" 
}   

function awkScript1() {
awk -F, -v cols="$1" -v hdr="$2" '
   BEGIN {OFS=FS}
   NR==1 {n=split(cols,cn); 
          for(i=1;i<=NF;i++) 
            for(j=1;j<=n;j++) 
              if($i==cn[j]) c[++k]=i; 
          $(NF+1)=hdr}
   NR >1 {v1=$c[1]; v2=$c[2]; v3=$c[3]; v4=$c[4]
          $(NF+1) = v1?(v1/(v1+v2+v3+v4)):0
         }1' "$3"
}

function awkScriptWrapper() {
   awkScript "$1" "$2"
}

function awkScriptWrapper1() {
   awkScript1 "$1" "$2"
}

awkScript "c1,c2,c3" "Header1" "input.txt" | awkScriptWrapper "c4,c5,c6" "Header2" >> output.txt
awkScript1 "c7,c8,c9,c10" "Header3" "input.txt" | awkScriptWrapper1 "c11,c12,c13,c14" "Header4" >> output1.txt 

output.txt的示例是:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header1,Header2
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,-1
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,-1,-1

output1.txt的示例是:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header3,Header4
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0.5

我的要求是我必须将Header1,Header2,Header3,Header4附加到同一个输入文件的末尾,即上面的脚本应该只生成1个输出文件&#34; finaloutput.txt&#34;:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header1,Header2,Header3,Header4
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,-1,0,0
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,-1,-1,1,0.5

我尝试做以下陈述:

awkScript "c1,c2,c3" "Header1" "input.txt" | awkScriptWrapper "c4,c5,c6" "Header2" >> temp_output.txt
awkScript1 "c7,c8,c9,c10" "Header3" "temp_output.txt" | awkScriptWrapper1 "c11,c12,c13,c14" "Header4" >> finaloutput.txt

但我没有得到它。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

假设您需要在管道中连接两个命令:

$ cmd1 | join --header -j1 -t, -o1.{1..17} -o2.16,2.17 - <(cmd2)
id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header1,Header2,Header3,Header4
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,-1,0,0
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,-1,-1,1,0.5

以上假设cmd1输出:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header1,Header2
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,-1
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,-1,-1

虽然cmd2输出:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,Header3,Header4
1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0
2,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0.5

它是如何运作的?

--header会将每个文件中的第一行视为字段标题
-j1将联合第一场 -t,指定,作为字段分隔符
-o xxx将指定输出列,1.1表示文件1中的第一列,在本例中为cmd12.1表示文件二中的第一列,在本例中为cmd2

-o1.{1..17}将扩展为:

-o1.1 -o1.2 -o1.3 -o1.4 -o1.5 -o1.6 -o1.7 -o1.8 -o1.9 -o1.10 -o1.11 -o1.12 -o1.13 -o1.14 -o1.15 -o1.16 -o1.17

这是一种快速指定cmd1的前17列的方法。

-是指标准输入,在这种情况下是cmd1的输出

<(command)process substitution

您可以更改为:

join [options] file1 file2

如果您需要加入两个常规文件。