awk |根据列值重新排列CSV文件的字段

时间:2013-11-22 15:07:34

标签: awk

我需要你帮助写下awk以解决下面的问题。我有一个源文件和它的所需输出。

源文件

  

一个:5,B:1,C:2,会话:4,E:8
  b:3,a:11,c:5,e:9,session:3,c:3

输出文件

  

会话:4,A = 5,B = 1,C = 2
  会话:3,a = 11,b = 3,c = 5 | 3

注意:

  • 字段未在源文件中组织
  • 在输出文件中:字段按其特定格式组织,例如:所有值都在第二列中,然后是b然后是c
  • 对于值c,在第二行中,它的n次出现,因此在输出中它与PIPE符号合并。

请帮忙。

2 个答案:

答案 0 :(得分:4)

尝试:

awk '
    BEGIN  { 
        FS = "[,:]"
        OFS = ","
    }
    {
        for ( i = 1; i <= NF; i+= 2 ) {
            if ( $i == "session" ) { printf "%s:%s", $i, $(i+1); continue }
            hash[$i] = hash[$i] (hash[$i] ? "|" : "") $(i+1)
        }

        asorti( hash, hash_orig )
        for ( i = 1; i <= length(hash); i++ ) {
            printf ",%s:%s", hash_orig[i], hash[ hash_orig[i] ]
        }
        printf "\n"
        delete hash
        delete hash_orig
    }
' infile

用任何逗号或冒号分割行并遍历所有奇数字段以将它们及其值保存在散列中以在末尾打印。它产生:

session:4,a:5,b:1,c:2,e:8
session:3,a:11,b:3,c:5|3,e:9

答案 1 :(得分:4)

适用于任何现代的awk:

$ cat file
a:5,b:1,c:2,session:4,e:8
a:5,c:2,session:4,e:8
b:3,a:11,c:5,e:9,session:3,c:3

$ cat tst.awk
BEGIN{ FS="[,:]"; split("session,a,b,c",order) }
{
    split("",val)               # or delete(val) in gawk
    for (i=1;i<NF;i+=2) {
        val[$i] = (val[$i]=="" ? "" : val[$i] "|") $(i+1)
    }

    for (i=1;i in order;i++) {
        name = order[i]
        printf "%s%s", (i==1 ? name ":" : "," name "="), val[name]
    }
    print ""
}

$ awk -f tst.awk file
session:4,a=5,b=1,c=2
session:4,a=5,b=,c=2
session:3,a=11,b=3,c=5|3

如果您确实希望打印e值,与发布的所需输出不同,只需将,e添加到BEGIN部分split()中的字符串,无论您希望这些值出现在有序输出中。

请注意,当上面第2行的输入中缺少b时,它会按照您的意愿输出空值。