Obtaining varied results using the grep command

77 Views Asked by At

For example, I have a file:

$ cat test.file
a
b
c

If I grep with output, I got echo $? to 0:

$ grep a test.file
a

$ echo $?
0

But if I grep without output, I got echo $? to 1

$ grep x test.file

$ echo $?
1

Because I got $? to 1, my pipeline with this command is failed.

What should I do to get consistent result as 0, since grep has no output is fine to me.

4

There are 4 best solutions below

2
On

Add || true to the end of the statement, for example:

grep x test.file > out.file || true

I prefer the above approach, since it is more explicit and more concise than setting/resettings errexit or pipefail like so:

set -o errexit
# ...
set +o errexit
grep x test.file > out.file
set -o errexit

This is especially true if you have multiple grep commands scattered throughout the script.

0
On

Simply add an or true and the end

grep not_found myinput.file || : # same as /usr/bin/true
1
On

A command in a pipeline failing only causes the rest of the pipeline to fail if you previously called set -o pipefail - if you don't want that behavior then don't set that option.

Having said that, you could just use awk instead:

$ awk '/a/' test.file
a
$ echo $?
0

$ awk '/x/' test.file
$ echo $?
0
0
On

You could use sed much like Ed's awk solution.

$: sed -n '/a/p' tst; echo $?
a
0

$: sed -n '/x/p' tst; echo $?
0

But as a rule, user3922090's ||: is my go-to for any time I don't want an error return, regardless of the result.

$: grep a file ||: ; echo $?
a
0

$: grep x file ||: ; echo $?
0

The || executes it's right-hand only if the left-hand returns a fail/error exit code, so if the grep finds a match, grep's zero is printed... but if grep doesn't, it returns an error, and || executes the :, which is a synonym for true, which just unconditionally returns a zero code - which is what gets printed by echo.