I want to group all the file contents based on the value of first column. It would be better if the output is in sorted form.


1 foo
2 bar
1 foobar
2 barbar
3 apple
4 banana
3 mango
5 orange

Expected output:

1 foo, foobar
2 bar, barbar
3 apple, mango
4 banana
5 orange
  • Could you clarify? Why would the expected output be 1 foo, foobar? What happened to 2 bar? Don't you want something like 1 foo, foobar\n 2 bar? – terdon Oct 20 '14 at 14:25

If I understand correctly, you're looking for

perl -lane 'push @{$k{$F[0]}},$F[1]; 
            END{$"=", ";print "$_ @{$k{$_}}" for sort keys(%k)}' file

There's no reason to explicitly split the line, the -a flag already does it for you. It will split each input line into the @F array. So, here we create the %k hash whose keys are the 1st fields and whose values are the corresponding lists of 2nd fields. Then, at the end, we sort the hash keys, set the list separator ($") to ,[space] and print each key and its corresponding list of values.

  • nice, but the command which uses hash displays the output in different order. – Avinash Raj Oct 20 '14 at 15:46
  • small update. the contents of the file is like 1 foo \n 2 bar \n 1 foobar \n 2 barbar list goes long, i want the output to be 1 foo, foobar \n 2 bar, barbar . \n is line break not a literal \n symbol. – Avinash Raj Oct 20 '14 at 15:51
  • 2
    @AvinashRaj come on, you know better than that! Don't post updates in comments, edit your question! I thought you only wanted the 1 lines. Now you say you also want the 2? As for the order, yes, the hash will change the order. If that is a problem, you should mention it in your question. – terdon Oct 20 '14 at 16:11
  • updated my question. – Avinash Raj Oct 20 '14 at 16:23

Another perl:

$ perl -anle '
    push @{$h{$F[0]}}, $F[1];
    END {
        for (sort {$a <=> $b} keys %h) {
            print "$_ ", join(", ", @{$h{$_}});
' file
1 foo, foobar
2 bar, barbar
3 apple, mango
4 banana
5 orange


  • We create a hash $h, which has keys are value $F[0]. Each hash's value is a array reference. When processing each line, we add value of the second field $F[1] to array reference push @{$h{$F[0]}}, $F[1].

  • After processing all lines, we sort the keys of $h (sort {$a <=> $b} keys %h), join each array reference to a string (join(", ", @{$h{$_}})), print each key corresponding with the join string.

  • +1 , i think it would be more helpful if you add an explanation. – Avinash Raj Oct 20 '14 at 16:51
  • @AvinashRaj: Updated explanation. – cuonglm Oct 20 '14 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.