# store all data here: my %data; while (){ chomp my @items = sort split m/,/; my %seen; # number the occurrences of data points, and put them into a hash for (@items) { my ($key, $val) = split m/ /, $_, 2; my $index = ++$seen{$key}; push @{$data{"$key$index"}}, $val; } } # now all data should be in the hash %data. use Data::Dumper; print Dumper \%data; # now print it: my @keys = sort keys %data; while (keys %data) { for (@keys) { if (exists $data{$_}) { # print it out here # then remove it shift @{$data{$_}}; delete $data{$_} unless @{$data{$_}}; } else { # print a placeholder here } } }