John Oliver
John Oliver

Reputation: 335

Find actual line number of line after a match

I want to edit some lines in an XML file. These lines will all look identical to begin with, they're just part of a block that comes after some other unique line, like:

First_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines
Second_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines
Third_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines

So, for each of First_Object, Second_Object, Third-Object, etc. I need to get the actual line number of true so I can change that value to some other value.

I started with "grep First_Object -A 100 filename | grep -n '[STATUS]'" (had to use square brackets instead of angles on this site) but that gave me the number of lines after First_Object, not the line number in question. I know I could add the two together, but that seems messy... there's got to be a way to get "the first occurrence of the string '[STATUS]' after the string 'First_Object' or something similar.

Thanks!

Upvotes: 0

Views: 70

Answers (2)

potong
potong

Reputation: 58351

This might work for you (GNU sed):

sed -nr '/^(First|Second|Third)/,/^<STATUS>/{/^<STATUS>/=}' file

This finds ranges of lines between lines beginning with First or Second or Third and the string <STATUS> and prints the line number of the line containing <STATUS>.

Upvotes: 0

jas
jas

Reputation: 10865

As mentioned, parsing XML is best left to an XML parser, but if you really have something as literally structured as your example data, something like this might help:

$ cat jo.awk
/_Object/ { obj = $0 }
/<STATUS>true<\/STATUS>/ { print obj ": line " NR ": " $0 }

bash-3.2$ cat jo.txt
First_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines
Second_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines
Third_Object
... some number of lines
<STATUS>true</STATUS>
... some number of lines

bash-3.2$ awk -f jo.awk jo.txt
First_Object: line 3: <STATUS>true</STATUS>
Second_Object: line 7: <STATUS>true</STATUS>
Third_Object: line 11: <STATUS>true</STATUS>

Upvotes: 1

Related Questions