根据公共字段将多行转换为一行(分组依据)

时间:2014-02-26 22:32:30

标签: shell unix awk

我有固定长度的文件(已排序),需要根据关键字段连接多行的字段。关键字段是前两列。前3行在开头有空格。实际文件中没有“空格”字样,我在这里保留格式。

输入文件

spaces2   001  111  111 Company Code         227                                
spaces2   001  111  111 Plan Code            012                                 
spaces2   001  111  111 Invoice Number       2014010                            
0000002     2  111  111 Company Code         214                                
0000002     2  111  111 Plan Code            20                                 
0000002     2  111  111 Invoice Number       3014010                            

期望的输出:

spaces2   001  111  111 Company Code         227-12-2014010                                
0000002     2  111  111 Company Code         214-20-3014010                                

有人可以建议如何做到这一点。

1 个答案:

答案 0 :(得分:2)

尝试这样的事情:

$ cat file
      2   001  111  111 Company Code         227
      2   001  111  111 Plan Code            012
      2   001  111  111 Invoice Number       2014010
0000002     2  111  111 Company Code         214
0000002     2  111  111 Plan Code            20
0000002     2  111  111 Invoice Number       3014010

$ awk '(($1,$2) in a){a[$1,$2]=a[$1,$2]"-"$NF;next}{gsub(/ *$/,"");a[$1,$2]=$0}END{for(x in a) print a[x]}' file
      2   001  111  111 Company Code         227-012-2014010
0000002     2  111  111 Company Code         214-20-3014010

请注意awk中的数组是关联的,因此输出的顺序是随机的。如果订单很重要,则需要使用其他代码进行处理。

如果订单对您至关重要,那么您可以执行以下操作:

awk '($1,$2) in seen {
    lines[i] = lines[i]"-"$NF; 
    next
}
{
    gsub(/ *$/,""); 
    seen[$1,$2]++; 
    lines[++i] = $0
}
END {
    for(line = 1; line <= length(lines); line++) {
        print lines[line]
    }
}' file

阐释:

  • ($1,$2) in seen:这会查找看到的数组中的前两个字段。如果它存在,它会将最后一个字段附加到数组行,next会跳过其余操作。
  • { .. } - 对于未在数组中看到的行执行此代码块。您的第一行将始终进入此处。因此,我们使用gsub删除尾随空格并填充数组seen并将该行存储在数组line中。
  • END块中,我们遍历数组line并打印它。由于我们使用增量索引,因此保留了顺序。 注意:这需要订购输入数据