Howto Use Sed to Remove Only Triple Empty Lines

Delete empty lines using sed

You may have spaces or tabs in your "empty" line. Use POSIX classes with sed to remove all lines containing only whitespace:

sed '/^[[:space:]]*$/d'

A shorter version that uses ERE, for example with gnu sed:

sed -r '/^\s*$/d'

(Note that sed does NOT support PCRE.)

How to use sed to remove only double empty lines?

I've commented the sed command you don't understand:

sed '
## In first line: append second line with a newline character between them.
1N;
## Do the same with third line.
N;
## When found three consecutive blank lines, delete them.
## Here there are two newlines but you have to count one more deleted with last "D" command.
/^\n\n$/d;
## The combo "P+D+N" simulates a FIFO, "P+D" prints and deletes from one side while "N" appends
## a line from the other side.
P;
D
'

Remove 1N because we need only two lines in the 'stack' and it's enought with the second N, and change /^\n\n$/d; to /^\n$/d; to delete all two consecutive blank lines.

A test:

Content of infile:

1

2
3

4

5

6

7

Run the sed command:

sed '
N;
/^\n$/d;
P;
D
' infile

That yields:

1
2
3

4

5

6
7

Howto use sed to remove only triple empty lines?

It's as simple as:

sed '1N;N;/^\n\n$/d;P;D'

SED command to delete empty lines till the first occurrence of sentence

If the lines are really empty (no whitespace), I would suggest

sed -n '/./,$p', otherwise sed -n $'/[^ \t]/,$p'. (The $'..' syntax makes bash expand the \t, so you don't need a sed that understands it.)

Remove blank lines in a file using sed

Use the following sed to delete all blank lines.

sed '/./!d' cou.data

Explanation:

  • /./ matches any character, including a newline.
  • ! negates the selector, i.e. it makes the command apply to lines which do not match the selector, which in this case is the empty line(s).
  • d deletes the selected line(s).
  • cou.data is the path to the input file.

Where did you go wrong?

The following excerpt from How sed Works states:

sed operates by performing the following cycle on each line of input: first, sed reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; each command can have an address associated to it: addresses are a kind of condition code, and a command is only executed if the condition is verified before the command is to be executed.

When the end of the script is reached, unless the -n option is in use, the contents of pattern space are printed out to the output stream, adding back the trailing newline if it was removed.8 Then the next cycle starts for the next input line.

I've intentionally emboldened the parts which are pertinent to why your sed examples are not working. Given your examples:

  • They seem to disregard that sed reads one line at a time.
  • The trailing newlines, (\n\n and \n\n\n in your first and second example respectively), which you're trying to match don't actually exist. They've been removed by the time your regexp pattern is executed and then reinstated when the end of the script is reached.

sed + remove # and empty lines with one sed command

If you're worried about starting two sed processes in a pipeline for performance reasons, you probably shouldn't be, it's still very efficient. But based on your comment that you want to do in-place editing, you can still do that with distinct commands (sed commands rather than invocations of sed itself).

You can either use multiple -e arguments or separate commands with a semicolon, something like (just one of these, not both):

sed -i 's/#.*$//' -e '/^$/d' fileName
sed -i 's/#.*$//;/^$/d' fileName

The following transcript shows this in action:

pax> printf 'Line # with a comment\n\n# Line with only a comment\n' >file

pax> cat file
Line # with a comment

# Line with only a comment

pax> cp file filex ; sed -i 's/#.*$//;/^$/d' filex ; cat filex
Line

pax> cp file filex ; sed -i -e 's/#.*$//' -e '/^$/d' filex ; cat filex
Line

Note how the file is modified in-place even with two -e options. You can see that both commands are executed on each line. The line with a comment first has the comment removed then all is removed because it's empty.

In addition, the original empty line is also removed.

UNIX: using tr to delete empty lines

tr on linux, at least, can squeeze repeated characters:

echo -ne $a
the quick
brown fox

jumps over
echo -ne $a |tr -s '\n'
the quick
brown fox
jumps over

remove all empty lines from text files while keeping format

  • Ctrl+H
  • Find what: \R^$
  • Replace with: LEAVE EMPTY
  • check Wrap around
  • check Regular expression
  • Replace all

Explanation:

\R      : any kind of linebreak
^ : begining of line
$ : end of line

Result for given example:

apples
oranges
peaches

Remove empty line before a pattern using sed

You'll need to add m flag for Test 1, so that ^ and $ anchors will match every line's start and end locations, otherwise they'll match start/end of entire string. This assumes m flag is supported by your implementation, like GNU sed does.

sed ':r;$!{N;br};s/^\n\(# \[END\)/\1/mg'

Test 3 works because there's a newline just before the empty line as part of that previous line. The below example might help you better visualize it:

$ printf 'a\nb\nc\n'
a
b
c
$ printf 'a\nb\n\nc\n'
a
b

c

With perl:

perl -0777 -pe 's/\n\K\n(?=# \[END)//g'
  • -0777 will slurp the entire input as single string
  • \n\K\n(?=# \[END) will match a newline provided there's a newline character before and # \[END after that newline

Another alternative with GNU sed, doesn't need to read whole file in one go.

sed '/^$/{N; s/\n\(# \[END\)/\1/; P; D}'
  • /^$/ will match an empty line
    • N add next line to pattern space
    • s/\n\(# \[END\)/\1/ remove the newline if required regexp matches

P and D are crucial here, so I'll quote the manual:

P Print out the portion of the pattern space up to the first newline.

D If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.



Related Topics



Leave a reply



Submit