我有一个巨大的文本文件,其数据如下: -
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
手动操作需要几天时间,所以我想知道它是否可以通过编程方式解决,或者是否有在线工具?
答案 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的解决方案,但不依赖于gawk
。 sed
删除该行中的最后一个逗号,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