awk:将具有唯一内容的行合并到同一id的每一行

时间:2019-01-16 20:39:42

标签: arrays string bash awk gsub

我有一个条目列表,每个条目都由一个换行符分隔,其中每个条目是一组用逗号分隔的值。此处的逗号分隔类似于每列的值。一些条目映射到相同的ID(每个条目的第一个值),但具有不同的国家和地区。 (在下面列出)

我正在尝试将具有相同ID,但可能具有不同国家和地区的条目分组到单个行条目,在该行条目中,将关联的多个国家和/或地区附加到相应的列并以“ %%%”序列。

到目前为止,我已经设法通过awk在某种程度上实现了这一目标,但是我的方法的副作用是,我现在在region列中有重复项。

因此,我不确定是否应该继续使用当前的基于awk的方法,还是扩展到可处理该工作的可扩展性更高的解决方案。

s/< //

list.csv的内容:

awk -F ',' -v OFS=',' '{x=$1;$1="";ctry[x]=ctry[x]$10"%%% ";$10="";a[x]=$0; str=a[x]; }END{for(x in a){outputString=("\n" x a[x] ctry[x]"\n"); gsub (/%%% \n/,"",outputString); print outputString}}' list.csv > final.csv

当前输出:

123123, Shelf Life Test,f,Other,066900,Germany,809900,Chem CMI,066900,Europe
123123, Shelf Life Test,f,Other,066900,Poland,810000,Chem CMI,066900,APAC
123123, Shelf Life Test,f,Other,066900,Spain,810100,Chem CMI,066900,APAC
123123, Shelf Life Test,f,Other,066900,France,2810200,Chem CMI,066900,North America
456456,Ammonium Citrus Esther,f,SupraTex Chem Analysis, 475000, Nigeria,814600,Chem Sensory,129475,MEA (Middle East and Africa)
789789,Archive 9 BASES II,f,HydroCare,066900,Belgium,211500,Chem CMI,066900,CIS (Commonwealth of Independent States)

预期输出:

789789,Archive 9 BASES II,f,HydroCare,066900,Belgium,211500,Chem CMI,066900,CIS (Commonwealth of Independent States)

456456,Ammonium Citrus Esther,f,SupraTex Chem Analysis, 475000, Nigeria,814600,Chem Sensory,129475,MEA (Middle East and Africa)

123123, Shelf Life Test,f,Other,066900,France,2810200,Chem CMI,066900,Europe%%% APAC%%% APAC%%% North America

3 个答案:

答案 0 :(得分:1)

请尝试以下操作:

awk -F, '{
    x=$1;
    if (!shown[x,$10]++)
        ctry[x]=ctry[x]$10"%%% ";
    if (!shown[x,$6]++)
        nation[x]=nation[x]$6"%%% ";
    a[x]=$1","$2","$3","$4","$5
    b[x]=$7","$8","$9
}
END{
    for(x in a){
        gsub (/%%% $/,"",nation[x]);
        gsub (/%%% $/,"",ctry[x]);
        print a[x]","nation[x]","b[x]","ctry[x]"\n";
    }
}' list.csv > final.csv

您将看到上面的脚本基于OP的脚本,并进行了一些重构和修改。重点是:if (!shown[x,$10]++)和下面类似的行,避免重复。

答案 1 :(得分:0)

一种方法:

awk -F, '($1 in a){x=a[$1];len=split(x,arr,",");arr[6]=arr[6]"%%% "$6;y=arr[1];arr[10]=arr[10]"%%% "$10;for(i=2;i<=len;i++){y=y","arr[i];a[$1]=y;}next;}{a[$1]=$0;}END{for(i in a){print a[i];}}' file

答案 2 :(得分:0)

尝试此Perl解决方案

$ cat ginzburg.txt
123123, Shelf Life Test,f,Other,066900,Germany,809900,Chem CMI,066900,Europe
123123, Shelf Life Test,f,Other,066900,Poland,810000,Chem CMI,066900,APAC
123123, Shelf Life Test,f,Other,066900,Spain,810100,Chem CMI,066900,APAC
123123, Shelf Life Test,f,Other,066900,France,2810200,Chem CMI,066900,North America
456456,Ammonium Citrus Esther,f,SupraTex Chem Analysis, 475000, Nigeria,814600,Chem Sensory,129475,MEA (Middle East and Africa)
789789,Archive 9 BASES II,f,HydroCare,066900,Belgium,211500,Chem CMI,066900,CIS (Commonwealth of Independent States)

$ perl -F, -lanE ' $x=join(",",@F[0..4]);$kv{$x}=join(",",@F[6..8]);@t=@{$kv2{$x}};push(@t,$F[5]);$kv2{$x}=[@t]; @p=@{$kv3{$x}};push(@p,$F[-1]);$kv3{$x}=[@p]; END { for(keys %kv) { %tv=(); %tv=map{$_=>1} @{$kv3{$_}};print "$_ ",join("%%",@{$kv2{$_}})," ",$kv{$_},",",join("%%",keys %tv) } } ' ginzburg.txt
456456,Ammonium Citrus Esther,f,SupraTex Chem Analysis, 475000  Nigeria 814600,Chem Sensory,129475,MEA (Middle East and Africa)
123123, Shelf Life Test,f,Other,066900 Germany%%Poland%%Spain%%France 2810200,Chem CMI,066900,Europe%%North America%%APAC
789789,Archive 9 BASES II,f,HydroCare,066900 Belgium 211500,Chem CMI,066900,CIS (Commonwealth of Independent States)

$