The issue I have with most, and perhaps all the answers here, is that they are losing the true exit code ($?) and mostly returning $? as 0. There is no way to differentiate if there was a match (exit code 0) or no match (exit code 1). This solution addresses that concern:
#!/bin/bash -e
echo "before"
exit_code=0
echo "anything" | grep e || exit_code=$?; if [[ $exit_code -ne 1 ]]; then (exit $exit_code); fi
echo "after"
exit
Explained
grep's exit status is either 0, 1 or 2:
0 means there was a match
1 means there was no match
2 means an error occurred
Now, with the above solution:
- If
grep returns 0, the test is not run and returns the true $? exit code of 0, and also sets $exit_code=0.
- If
grep returns 1, the test is run and returns a fake $? exit code of 0, but we also sets $exit_code=1 which can be used by future code to differentiate a match vs no match.
- If
grep returns any other value, the test is run and returns the true greater than 1 error exit code that should correctly halt the script, we also set $exit_code appropriately, but that won't matter because the script will halt.
-epresupposes you do care: so much so that any problem is catastrophic.var=$(complex command | grep complex_pattern)which may be null (in which case my program should not terminate). This is just a boiled down script which makes the problem occur. No metaphysical blackhole in the logic here, right? ;)