0

How can I add a string to the start of a line if the line and the next line start with numbers?

From:

random text
random text
65345
234
random text
random text
random text
random text
random text
random text
9875
789709
random text
random text
random text

To:

random text
random text
appended text 65345
234
random text
random text
random text
random text
random text
random text
appended text 9875
789709
random text
random text
random text

Adding to all lines that start with numbers is as simple as

$ printf "hello\n123\n" | sed 's/^[0-9]/appended text &/'
hello
appended text 123

No idea how to do what I am trying to do though.

"random text" might end in a number

Any ideas?

Chris
  • 985
  • 2
  • 7
  • 17
  • 1
    You should add a case to your example where 3 consecutive lines start with numbers and a case where lines contain numbers but not at the start of the line (some in middle, some at end), etc. i.e. all of the non-trivial cases. It's always easy to match on what you want but much harder to not match on what you don't want so it's important to create an example that covers all of your use cases. Don't just write "random text" - show us in your sample input/output the relevant examples of "random text". – Ed Morton Feb 02 '20 at 16:18

3 Answers3

1

This sort of thing is best done with awk. Something like:

awk 'prev ~ /^[0-9]/ && /^[0-9]/ { prev = "prepended text " prev} 
    NR>1 {print prev} 
    {prev=$0}
    END {print prev}' input 

Actually, it's probably "best" done in perl, but that seems to be unfashionable these days:

perl -0777 -pe '1 while s/(?<=^)(\d.*\n\d)/prepended text $1/cm' input
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • Your Perl program doesn't handle the output of `printf "123\n456\n"` (numbers on the first two lines) or `printf "abc\n123\n456\n789\n"` (more than two lines of numbers in a row) – ikegami Feb 02 '20 at 16:12
  • The first is easy to deal with: `perl -0777 -pe 's/(^[0-9].*\n[0-9])/prepended text $1/g'` – William Pursell Feb 02 '20 at 16:14
  • The awk seems to work great. I have tested it on my files and I haven't seen issue yet. Thanks – Chris Feb 02 '20 at 16:45
1

Just read in the whole file

perl -0777pe's/^(?=\d.*\n\d)/prepended text /mg'

You could also work with a two-line rolling window.

perl -ne'
   push @buf, $_;
   next if @buf < 2;
   $buf[0] = "prepended text $buf[0]" if $buf[0] =~ /^\d/ && $buf[1] =~ /^\d/;
   print(shift(@buf));
   END { print @buf; }
'

See Specifying file to process to Perl one-liner.

ikegami
  • 367,544
  • 15
  • 269
  • 518
0

This might work for you (GNU sed):

sed -E ':a;N;s/\n/&/2;Ta;s/\n([0-9]+\n[0-9]+)$/ \1/;ta;P;D' file

Open a window of 3 lines in the pattern space. If the 2nd and 3rd lines are numbers only, replace the 1st newline with a space and refill the window. Otherwise print/delete the first line in the pattern space and repeat.

potong
  • 55,640
  • 6
  • 51
  • 83