Babycece
Babycece

Reputation: 65

A linux shell script to find a string and add a few lines before the string

I'm new to this, just wondering if anyone could help :)

I have a file like this:

start1  
12.3  
13.2  
15.3  
end1

How do I find the string end1 and add a few lines before the string, so it looks like:

start1  
12.3  
13.2  
15.3  
NaN  
NaN  
end1

But the number of line added has to depend on a specific number, say 5. If it only has 3 entries between start1 and end1, the numbers of line added is 2.

Upvotes: 1

Views: 1289

Answers (7)

Ed Morton
Ed Morton

Reputation: 204015

It's really not clear whether that number you mention is always something you figure out from the file contents or something you might program but try this:

awk '
/start/ { c=0 }
/end/   { for (i=1; i<c; i++) print "NaN" }
{ print; ++c }
' file

and let us know of any problems.

EDIT: to add c lines if less than 5 lines exist:

awk '
/start/ { c=0 }
/end/ && c<5  { for (i=1; i<c; i++) print "NaN" }
{ print; ++c }
' file

or to pad up to 5 lines:

awk '
/start/ { c=0 }
/end/   { for (i=c; i<=5; i++) print "NaN" }
{ print; ++c }
' file

Upvotes: 1

potong
potong

Reputation: 58483

This might work for you (GNU sed):

sed -r '/^start/!b;n;:a;/\nend/bb;$!{N;ba};:b;/(\n[^\n]*){5}/!s/$/\nNaN/;tb;s/(\nend[^\n]*)(.*)/\2\1/' file

Upvotes: 0

Chris Seymour
Chris Seymour

Reputation: 85845

This is better suited to awk just set c to the number you require:

$ awk -vc=5 '/start/{n=0}/end/{for(i=0;i++<c+1-n;)print"NaN"}++n' file
start1  
12.3  
13.2  
15.3  
NaN
NaN
end1

$ awk -vc=8 '/start/{n=0}/end/{for(i=0;i++<c+1-n;)print"NaN"}++n' file
start1  
12.3  
13.2  
15.3  
NaN
NaN
NaN
NaN
NaN
end1

Upvotes: 0

Kent
Kent

Reputation: 195179

awk -vt=5 '/start1/{print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' file

you just replace the 5 in above one-liner to get different number of "NaN" :)

EDIT: start may not at 1st line.

awk -vt=5 '/start1/{i=0;print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' file

test

kent$  cat t
Empty lines followed




foo
foo1
start1  
12.3  
13.2  
15.3  
end1
bar
bar2

kent$  awk -vt=5 '/start1/{i=0;print;next;}/end1/{for(x=1;x<=t-i;x++)print "NaN";}++i' t
Empty lines followed




foo
foo1
start1  
12.3  
13.2  
15.3  
NaN
NaN
end1
bar
bar2

Upvotes: 1

camh
camh

Reputation: 42488

You can easily do this with awk(1):

awk '/start1/ {start=NR} /end1/ && start {for (i=NR-start;i<=5;++i) {print "NaN"}} 1'

That will record which line the string start1 was on, and when it sees the line the string end1, it will output up to 5 lines of NaN depending on how far apart start1 and end1 are. Change the 5 to be whatever you need.

Upvotes: 2

thb
thb

Reputation: 14454

I admit that I do not know a straightforward way to do what you want with Sed. Someone will probably post an Awk answer, which is fine, but if one does not mind the run-time cost of starting the Perl interpreter, this works, too:

perl -we 'print until eof() or ($_ = <>) =~ /^start1\s*$/; exit if eof(); print; my $i = 5; --$i, print until eof() or ($_ = <>) =~ /^end1\s*$/; --$i, print "NaN\n" until $i <= 0; print; print <>;'

Upvotes: 0

phaazon
phaazon

Reputation: 2002

You can use sed to do such a thing:

`sed /end1/lineToAdd0\nlineToAdd1\netc\nend1/g < file`

I’m not sure about the \n, I don’t remember if it’s sed that interprets it a special way.

Upvotes: 0

Related Questions