Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file whose content looks like this:

2009 150  0  0  0     0000
75.316   0.0400390625  0.00007        0.00000 0.8980
76.216   0.0400390625  0.00007        1.00000 0.9046
77.217   0.0400390625  0.00009        2.00000 0.9113
78.341   0.0400390625  0.00010        3.00000 0.9183
2009 150  2  0  0     0000
75.316   0.0400390625  0.00007        0.00000 0.8980
76.216   0.0400390625  0.00007        1.00000 0.9046
77.217   0.0400390625  0.00009        2.00000 0.9113
78.341   0.0400390625  0.00010        3.00000 0.9183
79.616   0.0400390625  0.00013        4.00000 0.9255

I would like to:

  1. Find all lines that start with keyword 2009.
  2. Pre-pend those lines to all following ones until another occurrence of line that starts with 2009 is found, and so on until EOF.

In essence I am looking for an output like this:

2009 150  0  0  0     0000 75.316   0.0400390625  0.00007        0.00000 0.8980
2009 150  0  0  0     0000 76.216   0.0400390625  0.00007        1.00000 0.9046
2009 150  0  0  0     0000 77.217   0.0400390625  0.00009        2.00000 0.9113
2009 150  0  0  0     0000 78.341   0.0400390625  0.00010        3.00000 0.9183
2009 150  2  0  0     0000 75.316   0.0400390625  0.00007        0.00000 0.8980
2009 150  2  0  0     0000 76.216   0.0400390625  0.00007        1.00000 0.9046

.......

I have been scratching my head on this for quite a while and cannot come up with a solution. Help would be appreciated. I know how to extract the text between keywords using flags but I am not sure if that is the right direction.

share|improve this question
    
Similar problem: stackoverflow.com/questions/22546395/… –  DigitalTrauma Apr 15 at 17:25
    
This is a very specific question which now has four very specific answers. Perhaps one of the people who voted to close this can explain exactly why they think this is too broad. –  Graeme Apr 15 at 23:23

3 Answers 3

You can use awk for this:

awk '/^2009/{a=$0;next}{print a" "$0} ' file.txt

This will only prepend a space to any lines before the first match of 2009, you can set a default string to prepend like this:

awk 'BEGIN{a="My default prepend string";}/^2009/{a=$0;next}{print a" "$0} ' file.txt
share|improve this answer
    
you are fast!!! –  user61786 Apr 15 at 14:46
    
Worked great. Thanks a million. Saved a lot of time and a big headache probably. –  user65305 Apr 15 at 15:03
    
@user65305 if this answer solves your issue please take a minute and check the check mark under the vote count to the left, this will [signify to everyone]((unix.stackexchange.com/help/someone-answers) that your issue's been resolved. –  terdon Apr 15 at 16:21

Using sed:

sed -n '
  /^2009/ { h }
  /^2009/ !{ G; s/^\(.*\)\n\(.*\)$/\2 \1/p }
  ' in_file

Explanation as requested:

-n - makes sed not print anything unless we tell it to.

/^2009/ { h } - when we reach a line beginning with 2009, put it in the hold buffer.

/^2009/ !{...} - the pattern inside the {...} is gets applied to every line that doesn't start with 2009.

G; s/^\(.*\)\n\(.*\)$/\2 \1/p - G copies the hold buffer and appends it the line just read into the pattern space. There are now two lines in the pattern space which we need to swap the order of and combine before printing. The replace pattern with back-references does just this.

share|improve this answer
    
You might want to explain how this works a little. –  terdon Apr 15 at 16:28
    
@terdon, updated –  Graeme Apr 15 at 20:03
    
Thanks, I'd upvote you but I already had. –  terdon Apr 15 at 22:49

I'd do this in Perl:

perl -lne 'if(/^2009/){$n=$_; next} print "$n $_"' file

or, more concisely

perl -lne '/^2009/ ? ($n=$_) : print "$n $_"' file

The idea is to save the current line ($_ in Perl) as $n if it begins with 2009 and if not, print the current line along with the current value of $n.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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