I want to write a function that always have a non empty output or fails, but I'm missing a command that read stdin and pipe it to stdout if non-empty or fails like:
example() {
do_something_interesting_here $1 | cat_or_fails
}
The idea is that if the command cat_or_fails
is given an empty input it fails (so the function fails) or the input is output without any changes (like cat
).
But I could not find any standard utility capable of that trick, or may be I'm not sure how to use those tools.
CodePudding user response:
Following the idea of @William Pursell in the comment it seems that grep can do the trick using something like:
example() {
do_something_interesting_here $1 | grep "[[:alnum:]]"
}
As mentioned in the comments, it will consume any empty lines (or any line that don't match the regex given).
CodePudding user response:
A simple algorithm to accomplish this is trivial and obvious: Try to read one byte. If it works, write that byte back out and then run cat
. If it fails, exit with a nonzero status.
Both below variants can be used in the manner described in the question (... | cat_or_fails
).
A very simple implementation (that doesn't try to handle binary files) would look like:
cat_or_fails() {
local firstbyte
IFS= read -r -n 1 firstbyte || return
printf '%s' "${firstbyte:-$'\n'}"
cat
}
A slightly less simple implementation that does try to handle binary files correctly might look like:
cat_or_fails() {
local firstbyte
IFS= read -r -d '' -n 1 firstbyte || return
if [[ $firstbyte ]]; then
printf '%s' "$firstbyte"
else
printf '\0'
fi
cat
}
CodePudding user response:
My usual trick to assure that at least one line of a text file is found follows. It is all standard shell stuff... bash, ksh, zsh.
example() {
set -o pipefail #assure failure on do_something is not suppressed
do_something_interesting_here $1 |
grep . #assure no output returns error
}
If you need pipefail to cancel when the function returns:
example() {
( #isolate pipefail in subshell
set -o pipefail #assure failure on do_something is not suppressed
do_something_interesting_here $1 |
grep . #assure no output returns error
)
}