How I can remove the previous line of a match pattern?
Or
the opposite of:
sed -n '/pattern/{g;1!p;};h'
Use tac | sed | tac
(Linux/Solaris) then it's next line after a match pattern :)
sed is an excellent tool for simple substitutions on a single line, for anything else just use awk:
$ cat file
here is a
a bad line before
a good line
in a file
$ awk 'NR==FNR{if (/good/) del[NR-1]; next} !(FNR in del)' file file
here is a
a good line
in a file
You can use the above idiom to delete any number of lines before and/or after a given pattern, e.g. to delete the 3 lines before and 2 lines after a given target:
$ cat file
-5
-4
-3
-2
-1
target
+1
+2
+3
+4
+5
$
$ awk 'NR==FNR{if (/target/) for (i=-3;i<=2;i++) del[NR+i]; next} !(FNR in del)' file file
-5
-4
+3
+4
+5
or to leave the target in place and just delete the lines around it:
$ awk 'NR==FNR{if (/target/) for (i=-3;i<=2;i++) if (i!=0) del[NR+i]; next} !(FNR in del)' file file
-5
-4
target
+3
+4
+5
All very clear, trivial, and scalable...
For "relatively complex" navigation around a search expression, ed
might be a good solution (comments are not part of the command):
ed testfile << EOF
/r.*o/ # Search the pattern
-1d # delete one line above
w # write
EOF
Here is an example (using <<<
and \n
to write as a single line):
sh$ cat testfile
john
paul
george
ringo
sh$ ed testfile <<< $'/r.*o/\n-1d\nw'
23
ringo
16
sh$ cat testfile
john
paul
ringo
You can revert the file and then delete the line after the matche pattern(which is simple), and then revert the result, here is the code:
tail -r|sed '/pattern/{n;d;}'|tail -r
Here is another awk
:
awk '/pattern/ {f=1} !f&&NR>1 {print p} {p=$0;f=0} END {print p}' file
A tac awk
version:
tac file | awk '1; /pattern/ {getline}' | tac
PS getline
should normally be avoided since it has many pitfalls, so then this:
tac file | awk '!p||NR!=p+1; /pattern/ {p=NR}' | tac
This might work for you (GNU sed):
sed '$!N;/\n.*pattern/!P;D' file
Keep a window of 2 lines and test the second of them for the pattern. If the pattern is present do not print the first line.
This would work but only if line count is more than 1 and pattern is not at the last line.
sed -n '/pattern/ { h; b }; 1 { h; b }; ${ H }; x; p' file
Better use awk
instead:
awk '!/pattern/ && NR > 1 { print p } { p = $0 } END { if (NR) print p }' file