496

I am trying to delete empty lines using sed:

sed '/^$/d'

but I have no luck with it.

For example, I have these lines:

xxxxxx


yyyyyy


zzzzzz

and I want it to be like:

xxxxxx
yyyyyy
zzzzzz

What should be the code for this?

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
jonas
  • 5,259
  • 4
  • 16
  • 11
  • 5
    your sed command looks fine, it should work – perreal May 07 '13 at 08:23
  • The above command wouldn't work even if you don't have a space/tab but [CR+LF line endings](http://en.wikipedia.org/wiki/Newline). – devnull May 07 '13 at 08:53
  • 1
    For awk, see: [Remove blank lines in awk](http://unix.stackexchange.com/q/128328/21471), or [using grep](http://stackoverflow.com/q/1611809/55075), in general, see: [How to remove blank lines from a file in shell?](http://unix.stackexchange.com/q/101440/21471) – kenorb May 05 '15 at 16:07

17 Answers17

811

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.)

Kent
  • 189,393
  • 32
  • 233
  • 301
  • 3
    @HuStmpHrrr gnu sed doesn't support PCRE at all. it is ERE with `-r` – Kent Feb 17 '15 at 03:19
  • 21
    OS X needed `sed -i "" '/^[[:space:]]*$/d'` ***``***, – jww Oct 04 '16 at 19:04
  • 2
    @BernieReiter `^\s*$` will match all "empty" lines, empty here means, the line contains no chars, or the line contains only empty strings (E.g. spaces). All matched lines will be removed by sed, with the `d` command. – Kent Feb 26 '17 at 19:41
  • Perhaps `sed '/\S/!d' file` – potong Jul 30 '20 at 10:59
203

I am missing the awk solution:

awk 'NF' file

Which would return:

xxxxxx
yyyyyy
zzzzzz

How does this work? Since NF stands for "number of fields", those lines being empty have 0 fields, so that awk evaluates 0 to False and no line is printed; however, if there is at least one field, the evaluation is True and makes awk perform its default action: print the current line.

Ramy
  • 20,541
  • 41
  • 103
  • 153
fedorqui
  • 275,237
  • 103
  • 548
  • 598
95

sed

grep

awk

wisbucky
  • 33,218
  • 10
  • 150
  • 101
Oleg Mazko
  • 1,720
  • 15
  • 10
  • 1
    These show up correctly in your online tool, but `[]` should *not* be escaped in a bracket expression, so the code here isn't correct for `\[\[:space:\]\]` or `\[ \t\]` - should be `[[:space:]]` and `[ \t]`. – Benjamin W. Aug 10 '18 at 13:52
  • 1
    @BenjaminW. Thanks for catching that. Those were not from the original author, but came from [Edit 3](https://stackoverflow.com/posts/39139322/revisions) when it was changed from regular text to "code", which then "exposed" the `\\` escaping. I have fixed them now. – wisbucky Apr 25 '19 at 22:41
84

sed '/^$/d' should be fine, are you expecting to modify the file in place? If so you should use the -i flag.

Maybe those lines are not empty, so if that's the case, look at this question Remove empty lines from txtfiles, remove spaces from start and end of line I believe that's what you're trying to achieve.

Community
  • 1
  • 1
Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
44

I believe this is the easiest and fastest one:

cat file.txt | grep .

If you need to ignore all white-space lines as well then try this:

cat file.txt | grep '\S'

Example:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

outputs

7
5
Vadim
  • 819
  • 6
  • 10
  • 13
    No need for `cat`, `grep` takes files as well: `grep . file.txt` – Ciro Santilli OurBigBook.com May 16 '16 at 15:35
  • 3
    Yes, I know, but the initial question did not mention whether the source is a file or something else, so the solution is what comes after "|", and before it just an example of a source. Simply to distinguish the solution from the source of lines. – Vadim May 17 '16 at 16:33
  • 2
    `grep '\S'` is definitely not portable. If you have `grep -P` then you can use `grep -P '\S'` but it's not supported on all platforms, either. – tripleee Jan 09 '17 at 06:53
  • The downside of `grep .` compared to the other solutions is that it will highlight all the text in red. The other solutions can preserve the original colors. Compare `unbuffer apt search foo | grep .` to `unbuffer apt search foo | grep -v ^$` – wisbucky Apr 25 '19 at 23:12
  • @wisbucky grep does not default to color output, but often it's enable via a shell alias or environment variable. Use `grep --color=never .` to override. – Clement Cherlin Oct 06 '22 at 17:28
18

Another option without sed, awk, perl, etc

strings $file > $output

strings - print the strings of printable characters in files.

user319660
  • 312
  • 3
  • 9
  • 1
    Do you mean `strings` instead of `string` ? – Mickael B. May 02 '20 at 01:06
  • 1
    "For each file given, GNU strings prints the printable character sequences that are at least 4 characters long..." so very short lines might give you a surprise if you're unaware of this. There is a `--bytes=min-len` option to allow shorter lines. – SouthwindCG Apr 24 '22 at 04:45
17

With help from the accepted answer here and the accepted answer above, I have used:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

This covers all the bases and works perfectly for my needs. Kudos to the original posters @Kent and @kev

Community
  • 1
  • 1
ConMan
  • 1,642
  • 1
  • 14
  • 22
7

The command you are trying is correct, just use -E flag with it.

sed -E '/^$/d'

-E flag makes sed catch extended regular expressions. More info here

5

You can say:

sed -n '/ / p' filename    #there is a space between '//'
fedorqui
  • 275,237
  • 103
  • 548
  • 598
tank
  • 63
  • 1
  • 4
4

You are most likely seeing the unexpected behavior because your text file was created on Windows, so the end of line sequence is \r\n. You can use dos2unix to convert it to a UNIX style text file before running sed or use

sed -r "/^\r?$/d"

to remove blank lines whether or not the carriage return is there.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Douglas Daseeco
  • 3,475
  • 21
  • 27
  • Hi, what is the `-r` flag doing and is it possible to combine it with `-i` to modify the file directly and avoid printing to screen. In addition, I think that this command would also work as `sed -r "/^\r$/d"` – Alexander Cska Nov 25 '18 at 12:34
3

This works in awk as well.

awk '!/^$/' file
xxxxxx
yyyyyy
zzzzzz
Claes Wikner
  • 1,457
  • 1
  • 9
  • 8
2

You can do something like that using "grep", too:

egrep -v "^$" file.txt
Lowbit
  • 21
  • 2
1

My bash-specific answer is to recommend using perl substitution operator with the global pattern g flag for this, as follows:

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

This answer illustrates accounting for whether or not the empty lines have spaces in them ([\ ]*), as well as using | to separate multiple search terms/fields. Tested on macOS High Sierra and CentOS 6/7.

FYI, the OP's original code sed '/^$/d' $file works just fine in bash Terminal on macOS High Sierra and CentOS 6/7 Linux at a high-performance supercomputing cluster.

0

If you want to use modern Rust tools, you can consider:

  • ripgrep:
    • cat datafile | rg '.' line with spaces is considered non empty
    • cat datafile | rg '\S' line with spaces is considered empty
    • rg '\S' datafile line with spaces is considered empty (-N can be added to remove line numbers for on screen display)
  • sd
    • cat datafile | sd '^\n' '' line with spaces is considered non empty
    • cat datafile | sd '^\s*\n' '' line with spaces is considered empty
    • sd '^\s*\n' '' datafile inplace edit
Kpym
  • 3,743
  • 1
  • 21
  • 18
-1

Using vim editor to remove empty lines

:%s/^$\n//g

-2

For me with FreeBSD 10.1 with sed worked only this solution:

sed -e '/^[     ]*$/d' "testfile"

inside [] there are space and tab symbols.

test file contains:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
fedorqui
  • 275,237
  • 103
  • 548
  • 598
Vitaly
  • 15
  • 3
-2

NF is the command of awk you can use to delete empty lines in a file awk NF filename and by using sed sed -r "/^\r?$/d"