4

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.

2
  • Similar problem: stackoverflow.com/questions/22546395/… Apr 15, 2014 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, 2014 at 23:23

3 Answers 3

5

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
3
  • you are fast!!!
    – user61786
    Apr 15, 2014 at 14:46
  • Worked great. Thanks a million. Saved a lot of time and a big headache probably.
    – user65305
    Apr 15, 2014 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, 2014 at 16:21
4

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.

4

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.

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

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.