235

I tried grep -v '^$' in Linux and that didn't work. This file came from a Windows file system.

palacsint
  • 28,416
  • 10
  • 82
  • 109
node ninja
  • 31,796
  • 59
  • 166
  • 254

18 Answers18

397

Try the following:

grep -v -e '^$' foo.txt

The -e option allows regex patterns for matching.

The single quotes around ^$ makes it work for Cshell. Other shells will be happy with either single or double quotes.

UPDATE: This works for me for a file with blank lines or "all white space" (such as windows lines with \r\n style line endings), whereas the above only removes files with blank lines and unix style line endings:

grep -v -e '^[[:space:]]*$' foo.txt
ars
  • 120,335
  • 23
  • 147
  • 134
  • That egrep would only work for files with zero or 1 space on the line, not for files with 2 or more spaces. Change ? to *. – Ed Morton Dec 08 '12 at 09:42
  • 8
    This should be `grep -E -v`, everything after `-e` is interpreted as the pattern. – jazzpi Aug 03 '15 at 17:10
  • 16
    `grep -v -e '^[[:space:]]*$' -e '^#' file` will give you all non-blank, non-comment lines in a script or config file (or any file type that uses the hash character for comments). – palswim Feb 27 '18 at 23:11
  • 7
    "The `-e` option allows regex patterns for matching." That is very **misleading**. `-e` is a (POSIX-)definition for: `This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-).` (from [the manual](https://linux.die.net/man/1/grep)). Grep already expects a (basic) regular expression by default. For this pattern, you may leave out `-e` entirely: `grep -v '^[[:space:]]*$' foo.txt`. – Yeti Jul 01 '20 at 10:22
  • If you're dealing with files that might have windows-style CR+LF line breaks but don't want to also exclude lines with other whitespace, then use this regex: `'^[[:cnrl:]]?$'`. – Chris Feb 03 '21 at 21:20
119

Keep it simple.

grep . filename.txt
Frej Connolly
  • 1,374
  • 1
  • 10
  • 11
39

Use:

$ dos2unix file
$ grep -v "^$" file

Or just simply awk:

awk 'NF' file

If you don't have dos2unix, then you can use tools like tr:

tr -d '\r' < "$file" > t ; mv t "$file"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
19
grep -v "^[[:space:]]*$"

The -v makes it print lines that do not completely match

===Each part explained===
^             match start of line
[[:space:]]   match whitespace- spaces, tabs, carriage returns, etc.
*             previous match (whitespace) may exist from 0 to infinite times
$             match end of line

Running the code-

$ echo "
> hello
>       
> ok" |
> grep -v "^[[:space:]]*$"
hello
ok

To understand more about how/why this works, I recommend reading up on regular expressions. http://www.regular-expressions.info/tutorial.html

Sepero
  • 4,489
  • 1
  • 28
  • 23
  • 2
    How and why does this work? Your answer would be much better if you could explain. For instance your regular expression matches the beginning of the string then one or more spaces using the POSIX standard then the end of the string, i.e. with grep -v it removes all lines that are only spaces. Right? What happens if there are no spaces; it's simply a newline character? – Ben Dec 07 '12 at 21:20
  • As my example shows, even only an empty line is removed (the first line). I added more information, so hopefully that helps. :) – Sepero Dec 08 '12 at 01:02
6

If you have sequences of multiple blank lines in a row, and would like only one blank line per sequence, try

grep -v "unwantedThing" foo.txt | cat -s

cat -s suppresses repeated empty output lines.

Your output would go from

match1



match2

to

match1

match2

The three blank lines in the original output would be compressed or "squeezed" into one blank line.

James Davis
  • 848
  • 8
  • 12
Senol Erdogan
  • 61
  • 1
  • 2
4

The same as the previous answers:

grep -v -e '^$' foo.txt

Here, grep -e means the extended version of grep. '^$' means that there isn't any character between ^(Start of line) and $(end of line). '^' and '$' are regex characters.

So the command grep -v will print all the lines that do not match this pattern (No characters between ^ and $).

This way, empty blank lines are eliminated.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
FatherMathew
  • 960
  • 12
  • 15
  • `-e` does not mean "the extended version of grep", maybe you are confused with `-E`? The manual clearly says that `-e` just explicitly says that a pattern follows. Since the pattern does not start with a dash, and you are only defining one pattern anyway, you might as well leave it out as by default grep expects one regex pattern: `grep -v '^$' foo.txt` (no need for extended regex functionality). Also it is worth mentioning that this does not eliminate the blank lines in the file, only that which is piped through the output. For that case, `sed -i` would be the right tool. – Yeti Jul 01 '20 at 10:09
4

Do lines in the file have whitespace characters?

If so then

grep "\S" file.txt

Otherwise

grep . file.txt

Answer obtained from: https://serverfault.com/a/688789

jspek
  • 438
  • 3
  • 10
3

I prefer using egrep, though in my test with a genuine file with blank line your approach worked fine (though without quotation marks in my test). This worked too:

egrep -v "^(\r?\n)?$" filename.txt
chryss
  • 7,459
  • 37
  • 46
3

This code removes blank lines and lines that start with "#"

 grep -v "^#" file.txt | grep -v ^[[:space:]]*$
2
awk 'NF' file-with-blank-lines > file-with-no-blank-lines
legoscia
  • 39,593
  • 22
  • 116
  • 167
Tim
  • 21
  • 1
2

It's true that the use of grep -v -e '^$' can work, however it does not remove blank lines that have 1 or more spaces in them. I found the easiest and simplest answer for removing blank lines is the use of awk. The following is a modified a bit from the awk guys above:

awk 'NF' foo.txt

But since this question is for using grep I'm going to answer the following:

grep -v '^ *$' foo.txt

Note: the blank space between the ^ and *.

Or you can use the \s to represent blank space like this:

grep -v '^\s*$' foo.txt
MarcT
  • 33
  • 3
1

I tried hard, but this seems to work (assuming \r is biting you here):

printf "\r" | egrep -xv "[[:space:]]*"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mvds
  • 45,755
  • 8
  • 102
  • 111
0

Use:

grep pattern filename.txt | uniq
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
baitisj
  • 229
  • 5
  • 5
  • `uniq` will reduce adjoining blank lines to just one blank line, but does not remove them completely. Still, I like trying to use `uniq` like that. Sorting first would effectively remove all blank lines--leaving just one, but rearranging the line order may not be acceptable. – Zach Young Jan 16 '13 at 02:43
  • Good point. This will also chomp repeated lines. I guess my solution introduces bugs. – baitisj Jan 17 '13 at 05:57
0

Using Perl:

perl -ne 'print if /\S/'

\S means match non-blank characters.

Majid Azimi
  • 5,575
  • 13
  • 64
  • 113
0

Here is another way of removing the white lines and lines starting with the # sign. I think this is quite useful to read configuration files.

[root@localhost ~]# cat /etc/sudoers | egrep -v '^(#|$)'
Defaults    requiretty
Defaults   !visiblepw
Defaults    always_set_home
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR
LS_COLORS"
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
stack ALL=(ALL) NOPASSWD: ALL
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

egrep -v "^\s\s+"

egrep already do regex, and the \s is white space.

The + duplicates current pattern.

The ^ is for the start

Jonni2016aa
  • 144
  • 1
  • 3
0

Read lines from file exclude EMPTY Lines

grep -v '^$' folderlist.txt

folderlist.txt

folder1/test

folder2
folder3

folder4/backup
folder5/backup

Results will be:

folder1/test
folder2
folder3
folder4/backup
folder5/backup
ADV-IT
  • 756
  • 1
  • 8
  • 10
0

You can either:

(1) show only non-empty lines:

grep .

or

grep '\S'

or

grep '[[:graph:]]'

(2) hide empty lines:

grep -v '^$'

or better:

grep -v '^\s*$'

or

grep -v '^[[:space:]]*$'
  • . or '.' = pattern matching any character . except line break (typically patterns should be quoted when grep is used in a shell command, but in this case we can skip them)
  • '\S' = pattern, where \S stands for a character that is not a white space character (read more on pcre2syntax - Perl-compatible regular expressions)
  • '[[:graph:]]' = pattern, where [[:xxxxx:]] stands for positive POSIX named set, and graph for pcre2syntax's character class "printing, excluding space"
  • -v = invert the sense of matching, to select non-matching lines (read more on grep's Matching Control options)
  • '^$' = pattern, where ^ stands for start of line, and $ for end of line (which equals to empty lines) - this will work with LF end of line sequence (Unix and Unix-like systems)
  • \s* = \s is a whitespace character and * means zero or more occurrences, so pattern '^\s*$' will work with both LF (Unix) and CRLF (Windows) end of line sequence
  • '^[[:space:]]*$' = pattern, where ^ stands for start of line, [[:xxxxx:]] for POSIX named set, space for PCRE2 character class "white space", * for zero or more occurrences and $ for end of line - this will also work with LF and CRLF files

On some versions of grep you may also have to use this option:

  • -E = extended-regexp - interpret pattern as extended regular expressions
Andrew
  • 1,386
  • 1
  • 9
  • 8