sed - Remove previous line and current line based on pattern

Related searches

I want to delete the previous line and current line based on pattern match on next line

This is my sample.txt

This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 16
This is test line 999
This is test line 17
This is test line 18

I want to match for pattern 999 and delete both itself and previous line

I am trying this command but i get no output

sed -Ene ':a;N;/999/{d;}; ba; P' sample.txt

This might work for you (GNU sed):

sed 'N;/\n.*999/d;P;D' file

Open a running window of two lines throughout the length of the file.

If the second line of the window contains 999 delete both lines.

Otherwise, print the first line of the window, delete the first line and repeat.

An alternative solution for line 1 or 2 or more contiguous lines containing 999:

sed -n ':a;$!N;/\n.*999/{:b;n;/999/bb;ba};/999/!P;D' file

Delete range of lines above pattern with sed (or awk), So “find a line and print the previous N lines” isn't going to work as is, unlike “find a line banana in the range from the current line -2 to the current line, delete. to find a line and print previous lines sed incorporates the built-in P rint primitive´┐Ż Just like in VIM, we will be using the d command to delete specific pattern space with SED. To begin with, if you want to delete a line containing the keyword, you would run sed as shown below. sed -i '/pattern/d' file. Where option -i specifies the file in place.

tried on gnu sed

 sed -Ez 's/[^\n]*\n[^\n]*999\n//g' sample.txt

How to delete the previous line after pattern match?, I want the pattern to be matched as "<td style=" but only the previous line "<td>" #!/usr/bin/env bash # @(#) s1 Demonstrate find match, delete previous line, ed. pl " Expected output:" cat $E # Find match, current line number is in symbol ". 21. Delete the line containing the pattern 'Unix' and also the next line: $ sed '/Unix/{N;d;}' file Cygwin Solaris AIX N command reads the next line in the pattern space. d deletes the entire pattern space which contains the current and the next line. 22. Delete only the next line containing the pattern 'Unix', not the very line:

Could you please try following(if ok with awk).

awk 'prev && $NF!=999{print prev ORS FNR,$0;prev="";next} $NF==999{prev=""} $NF!=999{prev=FNR FS $0}'  Input_file

Or if you have even number of lines and you want to take care of printing last odd even.

awk 'prev && $NF!=999{print prev ORS FNR,$0;prev="";next} $NF==999{prev=""} $NF!=999{prev=FNR FS $0} END{if(prev){print prev}}'  Input_file

Merging previous line using sed - UNIX and Linux Forums, I've been trying to merge a previous line when I find a pattern using sed with no luck. Once I find that, I want to merge the previous line with the current line. I am trying to delete lines in archived Apache httpd logs Each line has the pattern: Hi, I have a written a shell script to get the previous line based on the pattern. If the current line contains age is : 10, then do: x: swap the pattern and hold space so that the prior line is in the pattern space. p: print the prior line. d: delete the pattern space and start processing next line. x. This is executed only on lines which do not contain age is : 10. In this case, it saves the current line in the hold space.

With a more comprehensive sample input of:

$ cat file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18

Try this:

$ cat tst.awk
$NF == 999 {
    prev = ""
    next
}
{
    printf "%s", prev
    prev = $0 ORS
}
END {
    printf "%s", prev
}

$ awk -f tst.awk file
This is test line 12
This is test line 14
This is test line 15
This is test line 17
This is test line 18

or if you favor brevity over clarity:

$ awk '$NF==999{p="";next} {printf "%s",p; p=$0 ORS} END{printf "%s",p}' file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18

Notice that the above will work even if some other part of your line than the last field contained 999 or if the last field as 9999 instead of your target 999, it doesn't require 999 to be written/tested multiple times in the script, if you wanted to test, say, the 3rd field in the line instead of the last field you could just change $NF to $3 =, if you WANTED to test the whole line for a regexp you'd just change $NF==999 to /999/, it'll work even if your target string contains regexp metacharacters, and it will work in any awk in any shell on any UNIX box.

Sed One-Liners Explained, Part II: Selective Printing of Certain Lines, This part will explain sed one-liners for selective printing of certain lines. Awesome news: I have written an e-book based on this article series. It always keeps the last 10 lines in pattern space and at the very last line of input it quits The "11,$D" command executes the "D" command if the current line number is greater´┐Ż Every line in PATTERN_line.txt contains the line number, in each file, where the pattern exists. Now, I'm trying to use those numbers to delete all lines that come after the pattern to the file end. This means I need to keep the file from the head to the patten line which must be included.

For a sed1 solution, that handles all edge cases (999 in first 2 rows or consecutive rows of 999):

  sed '
    1{
      /999/d  # Special case needed for line 1. Delete if it contains 999.
    }
    $!N     # Append next line. $!N stops exit w/o printing at EOF.
    /999/d  # If pattern space contains 999, d & begin next cycle.
    P       # If we get to here, there is no 999. Print to first newline.
    D       # Delete to first newline.                                   
  ' FILE

Output:

This is test line 12
This is test line 13
This is test line 17
This is test line 18

1 Tested on both BSD (Mac OS X) & GNU sed.

sed - 25 examples to delete a line or pattern in a file, sed '/^ *$/d' file Cygwin Unix Linux Solaris AIX '*' indicates 0 Delete the lines starting from the pattern 'Linux' till the last line: $ sed And hence, the current and the previous line gets deleted on encountering the pattern Linux. The ${x;p;} ID BASE Version 1.4.2. ID JDK Version 5.1. Version 1.4.2. ID JDK How to delete the previous line after pattern match? Team, I am writing a shell script to perform few health checks of the system, where I need to delete the previous line in the text file after pattern match using sed (or) awk.

Thanks to all for the solution.-A, B, C options are not supported. Using HP-UX 11.11 Now, can i print just the previous line and the matching line? cat replace_all* | sed -n -e 'N;/Failure/p;' prints the previous line only for the first match, thereafter only matching lines are printed and not their previous lines.

It works by swapping hold and pattern spaces for each line read in - so the last line can be compared to the current each time. So when sed reads a line it exchanges the contents of its buffers - and the previous line is then the contents of its edit buffer, while the current line is put in hold space.

sed -e '/Pattern \line/,+1d' sample This is the output I am getting. this is another random line next after pattern line has occured without. now we have another let us see the output. next after pattern line is not removed when it occurs as a separate line not next to the pattern. As per Michael's comments, the above syntax is GNU extension.

Comments
  • sed is the best tool for doing s/old/new/ on individual strings. That's not what you're doing here so sed wouldn't be the best tool for the job so why do you want to use sed for it when it can be done clearer, simpler, more robustly, more portable, and/or more efficiently with some other tool? You should include a case where 999 appears as the first line of your input and where it appears on 3 contiguous lines to show how you want those handled and give us something to adequately test a potential solution against.
  • I think this was a great question @rgd.
  • This one won't work if 999 is in the first line. I solved it using a special case for line 1. Not sure if there's a better way.
  • @AlexHarvey the OP did not specify what should happen if the first line contains 999 nor what should happen when 2 or more lines contains 999. However see edit.
  • I think \n.* is not needed in the first regex?
  • @AlexHarvey i think that is for case to read 999 in second line only. Few questions 1. when we go from label B TO A, does the next line to be read is line which we initially left or it start from line where inner label B ends ? I want to know when n reads continuous line containing 999 and then when it go back to label A , then what will be the contents of N
  • It branches immediately and unconditionally like a goto statement
  • I want to use sed only
  • It's not that much simpler than my sed solution though is it? I take the portability point. Otherwise, instead of the magic N that appends to pattern space, you have a magic prev = $0 ORS that does the same as sed's N.
  • I didn't have to add comments for my code to be clearly understandable and there's nothing magic about a variable assignment. Also, unlike with seds N, if we wanted to enhance to delete, say, 10 lines before the target line instead of 1 I wouldn't have to write that statement 10 times to save 10 lines I'd just make prev a 10-line array with a loop to print it and if the OP wanted to be able to use a variable number of lines specified at run time that's exactly the same solution in awk as for a static value but impossible to do in 1 sed script.
  • The point is there's benefits to the awk script and no benefits to the sed script. With awk: need to print a count of deleted lines stderr? trivial. Need to test for 999 being in a specific field? trivial. Need to test for an input string (999) as literal when it contains regexp metachars? Trivial. Need to also delete lines AFTER the target line? Trivial. Need to only delete preceding lines if they contains some other string? Trivial. etc., etc.. With awk if/when the requirements change you usually just build on what you already have while with sed it's usually either impossible or a rewrite
  • Oh come on, awk is just python or C or any other algol-based language with fewer language constructs, half a dozen keywords, an implicit while read split loop and implicit ifs around the condition { action } blocks. sed on the other hand is vastly different in both syntax and semantics. wrt maintainability of a 5 line script - you don't just write a script a certain way in preparation for enhancing THAT script, you write it that way so that when the next similar task comes along you can write that next script essentially the same way but with small differences where necessary.
  • Writing maintainable scripts shouldn't something you decide to do when necessary, it should be what you do unless there's a pressing need not to, e.g. for performance reasons. Anyway, as I said in another thread it took me 10 years of using sed (and shell) to manipulate text before I decided to start using awk for things that were more than just s/old/new/ and it sounds like you're just at the beginning of your own journey with that and happy to continue it so - all the best.
  • Thanks for that , can you please tell me where i am wrong with my sed if i need to use flow control