2

Is it possible to transform this:

1 Alice
1 Bob
1 Cary
2 Dan
3 Eve
3 Fred 

into this:

1 Alice,Bob,Cary
2 Dan
3 Eve,Fred

using shell? (without Perl, Ruby, Python etc)

synapse
  • 499
  • 2
  • 6
  • 14
  • synapse, is this a school homework problem? It smells suspiciously like one, especially with the arbitrary limitation on how to solve the problem. – Phil Hollenback Mar 30 '11 at 07:47

4 Answers4

2

Yes, there's a few ways of doing this.

Sort is your friend: Sort Wiki.

As is Awk: Awk Howto.

Jonathan Ross
  • 2,183
  • 11
  • 14
  • Jonathan, if he can't use perl/python, I'd rather assumed that all external utilities were banned. I suspect it can be done in pure bash, but it looks so much like a homework exercise I decided not to bother. Synapse, if this is a real problem, can you tell us a bit more about it, and which external tools **are** available to us? – MadHatter Mar 30 '11 at 06:39
  • @MadHatter We both read that question differently :-) – Jonathan Ross Mar 30 '11 at 06:41
  • sorry, absolutely; I am in no way critical of your answer, and sort, awk (and sed) were the first tools my mind reached for as well, I think your recommendation is a good one. I could do with a bit more information about the actual problem, is all! – MadHatter Mar 30 '11 at 06:43
  • @MadHatter Hehe :-) – Jonathan Ross Mar 30 '11 at 06:54
  • @MadHatter The real thing is the output of md5sum | sort | uniq which was fed to Ruby for grouping and db processing. I was wondering what is possible without "real" programming languages. – synapse Mar 30 '11 at 20:15
  • @MadHatter Oh, actually it could've been my home assignment, but 1) ten years ago 2) csh 3) running on IBM PC/RT BSD. Good old days. – synapse Mar 30 '11 at 20:39
2

Using associative arrays in bash version 4:

declare -A ary
while read line; do
  set -- $line
  ary[$1]+="$2,"
done < input_file
for key in ${!ary[@]}; do
  printf "%s %s\n" $key ${ary[$key]%,}  # the "%," strips the trailing comma
done
glenn jackman
  • 4,630
  • 1
  • 17
  • 20
1

Crap I couldn't resist the challenge. Here's my solution in shell (bash to be exact) as a oneliner:

k=0; while read i j; do if [ $k -eq $i ]; then echo -n ",$j"; \
else [ $k -gt 0 ] && echo; echo -n "$i $j"; k=$i; fi; done \
</tmp/infile; echo

which produces the desired output, properly formatted:

1 Alice,Bob,Cary
2 Dan
3 Eve,Fred

Assumptions:

  1. 0 is not a valid entry in the first column of the data.
  2. the first column is already numerically sorted.

If #2 is not valid, you need to run the input through sort(1) first with a numeric sort to put it in the proper order.

If I find out I just answered your homework I will be extremely annoyed. My only consolation is that if your teacher sees what I wrote they will think you are nuts.

Phil Hollenback
  • 14,947
  • 4
  • 35
  • 52
  • No, that's not my homework. That's almost the last part of pipe to delete links to identical files in database wget/find/md5sum/sort/uniq/ruby. After I've written Ruby script to group and modify the db I was wondering if it's possible to do grouping using shell. – synapse Mar 30 '11 at 10:13
  • Just joking around, no offense meant.:) – Phil Hollenback Mar 30 '11 at 14:17
0

This one over at stackoverflow is very similar and has some good answers: https://stackoverflow.com/questions/380817/best-way-to-simulate-group-by-from-bash

HampusLi
  • 3,478
  • 17
  • 14