while (@t = split /\s+/, ){ push (@{$h{$t[0]}{$t[1]}}, "$t[2]:$t[3]"); } foreach $k (sort keys %h){ print "$k ", join(' ', map {$_, @{$h{$k}{$_}}} sort keys %{$h{$k}}),"\n"; } __DATA__ id1 name1 cat1 catname1 id1 name1 cat2 catname2 id2 name2 cat3 catname3 id3 name3 cat1 catname1 id3 name3 cat4 catname4