如何将此文本文件编辑为具有相同标头的合并信息

时间:2017-12-05 09:54:32

标签: awk sed

我有一个巨大的文本文件,其数据如下: -

EAST DUBBO - Unknown
EAST MAITLAND - 1892
EAST MAITLAND - 1902
EAST MAITLAND - 1920
EAST MAITLAND - 1937
EAST MAITLAND - 1940
EAST MAITLAND - 1956
EBOR - 1905
EBOR - 1911
EDEN - Unknown
ELLENBOROUGH - 1905
ELONG ELONG - 1920
ELONG ELONG - 1955

我需要它采用这种格式: -

EAST DUBBO - Unknown
EAST MAITLAND - 1892, 1902, 1920, 1937, 1940, 1956
EBOR - 1905, 1911
EDEN - Unknown
ELLENBOROUGH - 1905
ELONG ELONG - 1920, 1955

手动操作需要几天时间,所以我想知道它是否可以通过编程方式解决,或者是否有在线工具?

4 个答案:

答案 0 :(得分:2)

这可以通过使用datamash [1]的简短单线程来完成:

datamash -t - --sort groupby 1 collapse 2 < your_file.txt

输出:

EAST DUBBO - Unknown
EAST MAITLAND - 1892, 1902, 1920, 1937, 1940, 1956
EBOR - 1905, 1911
EDEN - Unknown
ELLENBOROUGH - 1905
ELONG ELONG - 1920, 1955

-t -将字段分隔符设置为短划线

--sort做了它所说的

groupby 1将第一个字段设置为您想要聚合的字段

collapse 2告诉datamash列出第二个字段中的相应值(而不是计算它们或进行其他操作)

为了它的乐趣,这里有另一个awk解决方案,类似于CWLiu的解决方案,但不依赖于gawksed删除该行中的最后一个逗号,sort确实排序。

awk 'BEGIN { FS="-"; OFS="-" }\
           { x[$1] = x[$1] $2 "," }\
       END { for( i in x ) print i, x[i] }'\
           your_file.txt | sed s'/.$//' | sort

[1]如果您的系统上已经没有datamash,那么您的包管理器肯定会拥有它。或者您可以下载最新版本here

答案 1 :(得分:0)

awk -F'-' -v OFS='-' '{a[$1]=(a[$1]=="")?$2:a[$1]","$2}END{PROCINFO["sorted_in"]="@ind_str_asc";for(i in a)print i,a[i]}' file
EAST DUBBO - Unknown
EAST MAITLAND - 1892, 1902, 1920, 1937, 1940, 1956
EBOR - 1905, 1911
EDEN - Unknown
ELLENBOROUGH - 1905
ELONG ELONG - 1920, 195

简要说明,

  • -F'-' -v OFS='-':将输入和输出字段分隔符设置为&#39; - &#39;
  • a[$1]=(a[$1]=="")?$2:a[$1]","$2:将$1设置为数组中的键,$2作为值。如果已设置a[$1],请将其附加到a[$1]
  • PROCINFO["sorted_in"]="@ind_str_asc":这只是gawk使用,用于按索引按升序排序,比较为字符串

答案 2 :(得分:0)

假设记录在公共密钥中是连续的

$ awk -F' - ' '{if(p!=$1){if(v) print v; p=$1; v=$0} 
                else v=v ", " $2}
           END {print v}' file           

EAST DUBBO - Unknown
EAST MAITLAND - 1892, 1902, 1920, 1937, 1940, 1956
EBOR - 1905, 1911
EDEN - Unknown
ELLENBOROUGH - 1905
ELONG ELONG - 1920, 1955

答案 3 :(得分:0)

假设输入行按排序顺序(或以其他方式分组),可以使用sed完成:

#!/bin/sed -f

:loop

# If we've reached the end, print it and exit
# (Not required for GNU sed, whose N command continues)
$q
# read another line of input
N
# if the two lines have the same beginning, join them and repeat
/^\(.*\) - .*\n\1 - /s/\n.* - /,/
tloop

# otherwise, print the first line and eliminate it
P
s/.*\n//
bloop