使用FUNCTION中的列标题从文件中提取列

时间:2016-12-14 08:51:58

标签: function shell awk

我访问了this question并获得了以下代码:

$ cols="c1,c2,c3"; header="Header"
$ awk -F, -v cols="$cols" -v hdr="$header" '
       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' Infile >> Outfile

输入文件:

id,c1,c2,c3
1,0,0,0
2,0,0,1
3,0,1,0
4,0,1,1
5,1,0,0
6,1,0,1
7,1,1,0
8,1,1,1

产生以下输出:

id,c1,c2,c3,Header
1,0,0,0,0
2,0,0,1,-1
3,0,1,0,-1
4,0,1,1,-1
5,1,0,0,10
6,1,0,1,0
7,1,1,0,0
8,1,1,1,0

有没有办法将上面的脚本作为函数调用,N次,参数是 - 从同一个输入文件中取出不同的列?

假设我有一个以下形式的输入文件:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9..........................c50
1,0,0,0,0,0,0,1,0,4,......................................
2,0,0,1,4,35,6656,34,6,3...............................
3,0,1,0,4,3,5,3,3,2...............................

在第一次函数调用期间,参数应为c1,c2,c3。然后下一个函数调用可以使用参数c7,c8,c9。接下来可以使用参数c4,c5,c6。在每个函数调用期间采用的参数顺序是无关紧要的。在1次通话期间,它可以是c4,c5,c6,而在下一次通话期间,它可以是c22,c23,c24。有没有办法在单个脚本中执行此操作?即,

脚本应包含以下内容:

function awk_script(c1,c2,c3,Header)
function awk_script(c12,c13,c14,Header1)
function awk_script(c20,c21,c22,Header2)

其中,对于上面的每个函数调用,控件应该转到上面提到的函数定义,执行操作并保存到输出文件(对每个函数调用都是独立的)。有没有办法做到这一点?

我是shell脚本和awk的新手。

最终输出文件的示例如下:

id,c1,c2,c3,c4,c5,c6,c7,c8,c9..........................c50,Header,Header1,Header2
1,0,0,0,0,0,0,1,0,4,......................................0,3,0,0
2,0,0,1,4,35,6656,34,6,3...............................0,1,-1,0
3,0,1,0,4,3,5,3,3,2...............................0,0,0,0

1 个答案:

答案 0 :(得分:-1)

我猜您正在寻找在bash或任何shell上运行的脚本,请将she-bang (#!/bin/bash)更改为您正在使用的相应shell。

#!/bin/bash

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 awkScriptWrapper() {
       awkScript "$1" "$2"
} 

awkScript "c1,c2" "Header" "file" | awkScriptWrapper "c3" "Header1"

# The very first function call should start with the `awkScript` and all the 
# subsequent calls should use the wrapper function i.e.

# awkScript "c4,c5,c6" "Header1" "file" | awkScriptWrapper "c7,c8,c9" "Header2"
相关问题