Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I delete a matching line and the previous one?

I need delete a matching line and one previous to it. e.g In file below I need to remove lines 1 & 2.

I tried "grep -v -B 1 "page.of." 1.txt and I expected it to not print the matchning lines and the context.

I tried the How do I delete a matching line, the line above and the one below it, using sed? but could not understand the sed usage.

---1.txt--
**document 1**                         -> 1
**page 1 of 2**                        -> 2

testoing
testing

super crap blah

**document 1**
**page 2 of 2**
like image 931
SpH Avatar asked Sep 11 '11 13:09

SpH


4 Answers

You want to do something very similar to the answer given

sed -n '
/page . of ./ { #when pattern matches
n #read the next line into the pattern space
x #exchange the pattern and hold space
d #skip the current contents of the pattern space (previous line)
}

x  #for each line, exchange the pattern and hold space
1d #skip the first line
p  #and print the contents of pattern space (previous line)

$ { #on the last line
x #exchange pattern and hold, pattern now contains last line read
p #and print that
}'

And as a single line

sed -n '/page . of ./{n;x;d;};x;1d;p;${x;p;}' 1.txt
like image 111
Hasturkun Avatar answered Sep 21 '22 04:09

Hasturkun


grep -v -B1 doesnt work because it will skip those lines but will include them later on (due to the -B1. To check this out, try the command on:

**document 1**                         -> 1
**page 1 of 2**                        -> 2

**document 1**
**page 2 of 2**
**page 3 of 2**

You will notice that the page 2 line will be skipped because that line won't be matched and the next like wont be matched.

There's a simple awk solution:

awk '!/page.*of.*/ { if (m) print buf; buf=$0; m=1} /page.*of.*/ {m=0}' 1.txt

The awk command says the following:

If the current line has that "page ... of ", then it will signal that you haven't found a valid line. If you do not find that string, then you print the previous line (stored in buf) and reset the buffer to the current line (hence forcing it to lag by 1)

like image 25
Foo Bah Avatar answered Sep 20 '22 04:09

Foo Bah


grep -vf <(grep -B1 "page.*of" file | sed '/^--$/d') file
like image 32
bash-o-logist Avatar answered Sep 22 '22 04:09

bash-o-logist


Not too familiar with sed, but here's a perl expression to do the trick:

cat FILE | perl -e '@a = <STDIN>;
                    for( $i=0 ; $i <= $#a ; $i++ ) { 
                     if($i > 0 && $a[$i] =~ /xxxx/) { 
                       $a[$i] = ""; 
                       $a[$i-1] = "";
                     }
                    } print @a;'

edit:

where "xxxx" is what you are trying to match.

like image 41
entitledX Avatar answered Sep 22 '22 04:09

entitledX