使用awk数组值作为列索引

时间:2018-03-07 20:41:53

标签: awk

数据:

<cfquery datasource="dsn" name="qry">
SELECT * FROM table
</cfquery>
<cfoutput>#serializeJSON(qry)#</cfoutput>

总体目标: 接受我关注的字段并生成包含数据中所有唯一列的多个文件的脚本。 E.g:

EMAIL,NAME,KEY,LOCATION
foo@gmail.com,Joe,ABC,Denver
bar@gmail.com,Jane,EFD,Denver
...

产地:

myScript.sh NAME LOCATION

到目前为止我所拥有的:

  • Bash脚本,它接受一些任意数量的字段并将其存储在数组中
  • 查找字段的列索引号并将其存储在数组中

我正在努力:

  • 使用AWK接收索引数组,然后吐出我指定的字段的所有唯一组合,然后将其存储在数组中
  • 遍历该字段组合数组,为每个组合打印出一个文件,其中包含数据中包含这些列中这些值的所有行

第一步的我的AWK命令看起来像:

Joe_Denver.csv - contains all lines with "Joe" and "Denver" in the
NAME and LOCATION columns
Jane_Denver.csv - contains all lines with "Jane" and "Denver" in the NAME and LOCATION columns

那就是我希望将awk -F, -v colIdxs="${bashIdxs[*]}" '!seen[$colIdxs[*]]++ {print $colIdxs[*]}' 中存储的索引用作awk脚本中的列索引(其中bashIdxs可以是任意大小)。

如何做到这一点?另外,如果有更好的方法来完成我想要做的事情(我确信有),我也很想知道好奇心。

2 个答案:

答案 0 :(得分:2)

未经测试但如果不完全正确将会关闭:

colNames="$*"
awk -v colNames="$colNames" '
BEGIN {
    split(colNames,tmp)
    for (i in tmp) {
        names[tmp[i]]
    }
    FS=OFS=","
}
NR==1 {
    for (i=1; i<=NF; i++) {
        if ($i in names) {
            f[++nf] = $i
        }
    }
    hdr = $0
    next
}
{
    out = ""
    for (i=1; i<=nf; i++) {
        out = (out=="" ? "" : out "_") $(f[i])
    }
    out = out ".csv"
    if ( !seen[out]++ ) {
        print hdr > out
    }
    print > out
}
' file

如果您不使用GNU awk并获得“太多打开文件”错误,则需要将print > out更改为print >> out; close(out)

答案 1 :(得分:1)

awk救援!

$ awk -F, -v cols='NAME,LOCATION' '
        NR==1 {for(i=1;i<=NF;i++) if(FS cols FS ~ FS $i FS) sel[i]; h=$0; next}
              {key=""; 
               for(i=1;i<=NF;i++) if(i in sel) key=(key==""?$i:key"_"$i); file=key".csv"; 
               if(!(key in header)) {print h > file; header[key]} 
               print > file}' file

给出

$ head *_*.csv
==> Jane_Denver.csv <==
EMAIL,NAME,KEY,LOCATION
bar@gmail.com,Jane,EFD,Denver

==> Joe_Denver.csv <==
EMAIL,NAME,KEY,LOCATION
foo@gmail.com,Joe,ABC,Denver

NB。如果为您的操作系统打开的文件太多(根据输入数据和唯一键的数量),您可能需要关闭文件...