Sed: delete the previous line

I need to delete an empty string before matching.

So set the file:

random text more random text #matchee 

I need to match the template / # matchee /, and then remove the empty line in front of it.

Here is what I tried - no success:

 sed '/^[ \t]*$/{N;/#matchee.*$/{D;}}' file.txt 

My logic is:

  • If an empty string; add the following line to the drawing space / empty line \ n ... etc /
  • If the template space contains / # matchee /, Delete up to newline yielding / # matchee /

Basically, / matchee / is a constant that should be supported, and I need to remove the extra blank line from each entry in the file of entries marked with / # matchee /.

This has no effect. I am RTFM-ing and D must remove the pattern space to a new line. Since N adds a new line plus the next line --- this should give the desired results .... alas .... no and no. Is it because the match contains almost nothing (blankline)?

+4
source share
2 answers

Your approach will work if there is an odd number of empty lines, but it will fail if there is an even number. Your sed script is a loop of the following.

  • take line L1 and add it to the drawing space
  • If L1 is not empty, print it; but if it is empty:
    • take another line, L2 and add it to the template space
    • if L2 contains #matchee , drop L1 from the template space
    • print a pattern space that consists of either L1 and L2, or L2

You will notice that L2 is always printed, even if it is empty and a line containing #matchee . It is protected by the fact that it immediately follows an odd number of empty lines.

Edited to add: To fix the problem described above, you can add an inner loop using the : command to create a label and the b command to β€œfork” it (goto). It:

 sed '/^[ \t]*$/{: a;N;/#matchee/!P;D;/^[ \t]*$/ba}' file.txt 

is a loop of the following:

  • take line L1 and add it to the drawing space
  • If L1 is not empty, print it; but if it is empty:
    • create shortcut a & larr; it's non-op, just a place for goto
    • take another line, L2 and add it to the template space
    • if L2 does not contain #matchee , type L1
    • drop L1 from the template space (whether or not we printed it)
    • now we can think of L2 as L1; this is the only one in the template space
    • if rechristened L1 is empty, goto a
+5
source

This might work for you:

 sed '$!N;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt 

To keep track of how this works:

 sed '$!N;l;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt 

NB P prints to the first new line, D deletes the first line of the new line and starts a new cycle without reading in another record, if there is no new line, in which case it behaves like D and reads in the line and starts the next cycle.

+2
source

Source: https://habr.com/ru/post/1400663/


All Articles