Solved grep '^$' vs. grep -E '^[[:space:]]{1}$'

Hi,

I'm not sure, if this is a bug or I'm just losing it. The task: Display all empty lines in a file using grep.

Me, easy: grep -E '^[[:space:]]+$' 😍

Why? Because there are no empty lines, there is always a newline character, without you got no empty line.

Correct answer: grep '^$' :-/

Well, ok, according to the documentation '\n' (a.k.a newline) character is not treated as a real character, hence that is the correct answer. :what:

So I tried this on 14.2-RELEASE-p2 using:


$ /usr/bin/grep --version
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD



$ pkg which /usr/local/bin/ggrep
/usr/local/bin/ggrep was installed by package gnugrep-3.12


Not working! I checked several times that there are no space/tab character in that 'empty' line, nope no success. :eek:

How did I check ? I used vim and : grep -E '^[[:space:]]{1}$'

So I thought by myself perhaps I need to try this on linux, like Alma Linux 9.4:


$ rpm -qf /usr/bin/grep
grep-3.6-5.el9.x86_64


And, it works ! o_O

Any help would be highly appreciated.
 
on 13.5 grep '^$' works as it should
you can try grep -v . also
Doesn't work either on 14.2-p2, but does work on Linux.

I transferred the test file form Linux to my Bsd machine and it works as well. So I guess there must be something in my first file?!:oops:
 
On stable/14, amd64 at commit 677465720ad1,
Code:
% cat /usr/ports/x11/nvidia-driver/Makefile.common 
# LICENSE_FILE is set in the consumer ports because its location varies
LICENSE=    NVIDIA
LICENSE_NAME=    License For Customer Use of NVIDIA Software
LICENSE_PERMS=    dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept

.if ${DISTVERSION:R} > 390
ONLY_FOR_ARCHS=    amd64
.else
ONLY_FOR_ARCHS=    i386 amd64
.endif

ARCH_SUFX=    x86${ARCH:S/i386//:S/amd/_/}

# NVVERSION is float since r372065 (integer values become less readable
# after minor version could occupy three digits)
.if ${DISTVERSION:C/[0-9]+//g} == ".."                # major.minor.update
.  if ${DISTVERSION:C/[0-9]+\.([0-9]+)\.[0-9]+/\1/} < 100
NVVERSION=    ${DISTVERSION:S/./.0/:R}${DISTVERSION:E}    # allow minor > 99
.  else
NVVERSION=    ${DISTVERSION:R}${DISTVERSION:E}
.  endif
.else                                # major.minor
.  if ${DISTVERSION:E} < 100
NVVERSION=    ${DISTVERSION:S/./.0/}                # allow minor > 99
.  else
NVVERSION=    ${DISTVERSION}
.  endif
.endif
% grep  -v -e '^$' /usr/ports/x11/nvidia-driver/Makefile.common
# LICENSE_FILE is set in the consumer ports because its location varies
LICENSE=    NVIDIA
LICENSE_NAME=    License For Customer Use of NVIDIA Software
LICENSE_PERMS=    dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept
.if ${DISTVERSION:R} > 390
ONLY_FOR_ARCHS=    amd64
.else
ONLY_FOR_ARCHS=    i386 amd64
.endif
ARCH_SUFX=    x86${ARCH:S/i386//:S/amd/_/}
# NVVERSION is float since r372065 (integer values become less readable
# after minor version could occupy three digits)
.if ${DISTVERSION:C/[0-9]+//g} == ".."                # major.minor.update
.  if ${DISTVERSION:C/[0-9]+\.([0-9]+)\.[0-9]+/\1/} < 100
NVVERSION=    ${DISTVERSION:S/./.0/:R}${DISTVERSION:E}    # allow minor > 99
.  else
NVVERSION=    ${DISTVERSION:R}${DISTVERSION:E}
.  endif
.else                                # major.minor
.  if ${DISTVERSION:E} < 100
NVVERSION=    ${DISTVERSION:S/./.0/}                # allow minor > 99
.  else
NVVERSION=    ${DISTVERSION}
.  endif
.endif
% grep  -e '^$' /usr/ports/x11/nvidia-driver/Makefile.common



%
 
Seems like the file had been some additional special characters.


# works
grep -E '^[[:space:]]*$'
# fails
grep -E '^[[:space:]]+$'
# fails
grep -E '^[[:space:]]{1}$'
# works
grep -v .
# works
grep '^$'


However, I'm still confused, in particular on those that fail. I would at least expect grep -E '^[[:space:]]+$' to succeed as the previous did.
 
[…] Display all empty lines in a file using grep. […]
An empty line is, quote,​
A line consisting of only a <newline>; […]
your first draft, however, looks like you wanted non-empty blank lines
Blank Line
A line consisting solely of zero or more <blank> characters terminated by a <newline>; […]
To summarize:​
Bash:
grep -v '.'              my_file # empty lines
grep -E '^[[:blank:]]*$' my_file # blank lines
I have, like covacat, no problems with said commands. They filter blank or empty lines as advertised. And the grep -E '^[[:space:]]{1}$' finds lines containing exactly just one space character.​

PS: Gosh, now I see you wanted grep(1) to match multiple lines at once, the matching string spanning across multiple lines. That’s not how (standardized) grep(1) works, though.​
 
Back
Top