I have a dataset as such:

Name:      Jim Bean
Vice:      Dice
LoginTime: 12343314

Name:      Bob Dylon
Vice:      Trumpets
LoginTime: 12343314

Name:      Mary Jane
Vice:      Gambling
LoginTime: 12343314


I need to arrange this into a columnar format. My first thought is to use awk. But I'm a bit stuck.

The labels will always appear in the same order, also it will always show the same number of label/value pairs in each group (headers aren't important).

My question is: How would I do this?

I've seen hints that the command rs may be able to do something like that, but it's not standard on all systems.


You should post desired output with your question. My guess was this:

$ awk '{ if($2) printf("%s ", $2); else print ""; }' < dataset
Bob Trumpets AFD232SFDSFASFA 12343314 
Mary Gambling EWDSFDSFASFA 12343314

Note that this is an awfully stupid method, it does not validate anything at all. If your input looks any different from what you posted it will probably break.

  • You're right... I'm going to update this question to include last names in the names... which will make this fail. Is there a way to make this quote the values? – monksy Feb 7 '13 at 23:52
  • Silly me just add in: " $1=""; printf("%s ", $0); " and I'll accept the answer – monksy Feb 7 '13 at 23:56
  • Are you sure? If you have spaces in your fields, using space as column separator you won't be able to tell where one column ends and the next one starts. Maybe you want tab or zero as separator? Your question unfortunately leaves much to interpretation, hence you're getting weird answers such as mine. – frostschutz Feb 8 '13 at 2:35
  • You're right about that. Thor's answer does look tempting. Although I did upvote you. – monksy Feb 8 '13 at 6:32

You can do it like this with GNU awk, note the use of RS and FS:

<infile awk '{ print $2, $4, $6, $8 }' RS='\n\n' FS=': +|\n' OFS='\t'

If you want to keep the header:

<infile awk 'NR==1 { print $1, $3, $5, $7 } { print $2, $4, $6, $8 }' RS='\n\n' FS=': +|\n' OFS='\t'

Assuming all your records are formatted like this, you could do it like this with coreutils:

<infile grep -v '^$' | tr -s ' ' | cut -d' ' -f2- | paste - - - -


Jim Bean    Dice    AFDSDFDSFDSFASFA    12343314
Bob Dylon   Trumpets    AFD232SFDSFASFA 12343314
Mary Jane   Gambling    EWDSFDSFASFA    12343314

Output with header:

Name    Vice    ID      LoginTime
Jim Bean        Dice    AFDSDFDSFDSFASFA        12343314
Bob Dylon       Trumpets        AFD232SFDSFASFA 12343314
Mary Jane       Gambling        EWDSFDSFASFA    12343314
  • Nice, +1. What exactly is the field separator? Is it (: followed by one or more spaces) OR (newline)? – terdon Feb 8 '13 at 2:05
  • @terdon: it's actually both, as you may notice $1 refers to the first label, and $2 refers to its value, $3refers to the second label $4to $3's value etc. – Thor Feb 8 '13 at 2:23
  • Yes, that's what I meant by OR. Brilliant, I did not know I could give multiple FSs to gawk. – terdon Feb 8 '13 at 2:48
  • I'm not sure what it was but the $2 ... with the even numbers miss parsed some of the fields and it threw off everything. – monksy Feb 8 '13 at 20:30
  • @monksy: is the input tab-delimited? in that case use FS=':[\t ]*|\n'. – Thor Feb 8 '13 at 22:15

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.