Exit with non-zero if input is empty - jq

I am trying to parse my curl output with JQ and check the exit code, so when my curl output is empty, JQ return 0 exit code.
For example:
$ echo "" | jq '.key'
$ echo $?
0
How to make this return 1 or some non-zero value?

You should use input with -n/--null-input on the command line. This way JQ will fail if its input is empty.
$ echo | jq -n 'input.key'
jq: error (at <stdin>:1): break
$ echo $?
5
$ jq -n '{key: 1}' | jq -n 'input.key'
1
$ echo $?
0

If you want to specify the return code when the input is empty, you could use halt_error/1, like so:
$ echo "" | jq -n 'try input.key catch halt_error(9)' 2> /dev/null
$ echo $?
9

Related

How to test empty input?

The following command finishes silently when the input is empty. How to test for empty input and do something different depending on whether the input is empty or not?
$ jq -e -r .data < /dev/null
$ echo $?
0
One way would be to use the -s option and test for the empty array:
jq -s 'if . == [] then "empty" else .[0].data end' </dev/null
empty
But what else should be considered an empty input? As JSON ignores newlines etc., there could be an actual input which is considered an empty JSON:
echo | jq -s 'if . == [] then "empty" else .[0].data end'
empty
While the expected case will pass...
echo '{"data":1}' | jq -s 'if . == [] then "empty" else .[0].data end'
1
...other non-empty cases may not be caught as with the empty case
echo '{"other":1}' | jq -s 'if . == [] then "empty" else .[0].data end'
null
However, to elaborate more, you'd need to specify what "do something different" means. If you wanted to fail, like with the -e option but with a custom error message, you could read in the whole input as raw text using the -Rs option, then try to convert it to JSON using the fromjson builtin, and react upon that if it failed using the ? and // operators:
jq -Rs 'fromjson? // error("Bad input") | .data' </dev/null
jq: error (at <stdin>:1): Bad input
echo | jq -Rs 'fromjson? // error("Bad input") | .data'
jq: error (at <stdin>:1): Bad input
echo '{"data":1}' | jq -Rs 'fromjson? // error("Bad input") | .data'
1
You can use
jq -ne 'input? // null'
$ echo {} | jq -ne 'input? // null' >/dev/null; echo $?
0
$ echo '' | jq -ne 'input? // null' >/dev/null; echo $?
1
$ </dev/null jq -ne 'input? // null' >/dev/null; echo $?
1
If you also want to check that .data isn't missing and isn't null (or false), you can use
jq -ne 'input? // null | .data'
$ echo '{"data":123}' | jq -ne 'input? // null | .data' >/dev/null; echo $?
0
$ echo '{"data":null}' | jq -ne 'input? // null | .data' >/dev/null; echo $?
1
$ echo {} | jq -ne 'input? // null | .data' >/dev/null; echo $?
1
$ echo '' | jq -ne 'input? // null | .data' >/dev/null; echo $?
1
$ </dev/null jq -ne 'input? // null | .data' >/dev/null; echo $?
1

What exit code 1 of linux jq means

As the tile says, I wonder when jq exits with code 1. In its manual, it says -e sets the exit status of jq to 0 if the last output values was neither false nor null, 1 if the last output value was either false or null. Not clear what it means by the last output values of false or null? what if I don't use -e?
The following is intended to supplement the information given about the -e option elsewhere on this page.
Assuming -e has NOT been specified, the return code is:
5 if a call to error/1 or halt_error/0 causes program termination
an integral value (*) depending on N if halt_error(N) causes program termination, where N is a number; in particular, if N is non-negative, then the status is set to (N%256).
Otherwise, but still assuming -e has NOT been specified, the return code is:
2 if a parsing error reading input causes program termination
3 or 4 if a syntax error in the jq program causes program termination
0 on normal termination.
(*) Specifically:
N % 256 | if . < 0 then 256+. else . end
This answer is based on current jq 1.6 source code from https://github.com/stedolan/jq
With --exit-status (-e), there are 6 possible exit codes:
0: jq output something and last line was neither false nor null
1: last line output was false or null
2: usage problem or system error
3: jq program compile error
4: jq didn't ouput anything at all
5: unknown (unexpected) error: any error other than 2 and 3
Without --exit-status (-e), 0 just means that jq ran successfully. Additionally, exit status 1 and 4 disappear and 0 is returned instead.
Here is (Unix Bourne shell) some ways to get 1 as an exit value:
$ echo false | jq -e .
false
$ echo '{ "foo": false }' | jq -e .foo
false
$ echo null | jq -e .
null
$ echo '{ "foo": null }' | jq -e .foo
null
$ echo '{ }' | jq -e .foo
null
$ echo '{ "foo": false }' | jq -e '.bar?'
null
Here is how to get 4:
$ echo 'false' | jq -e '.foo?'
And (I'm sure you want to know) here is one way to get 5:
$ echo false | jq .foo
jq: error (at <stdin>:1): Cannot index boolean with string "foo"

recovering deleted script running in background

I have script which is running in bg(nohup) but it was accidently deleted,but that is continue running now I need to edit the code which is already deleted.
How can I now get that code.I assume somewhere it should be as it is running.
Try this :
#!/bin/bash
if [[ ! $1 || $1 == -h || $1 == --help ]]; then
echo -e "Usage:\n\n\t$0 '[path/]<file name>'"
exit 1
fi
files=(
$(file 2>/dev/null /proc/*/fd/* |
grep "(deleted)'$" |
sed -r 's#(:.*broken\s+symbolic\s+link\s+to\s+.|\(deleted\).$)# #g' |
grep "$1" |
cut -d' ' -f1
)
)
if [[ ${files[#]} ]]; then
for f in ${files[#]}; do
echo "fd $f match... Try to copy this fd to another place quickly!"
done
else
echo >&2 "No matching fd found..."
exit 2
fi
Not tested on non GNU-Linux

if [ $? -ne 0 ] then syntax error then unexpected

I have been trying to execute the following UNIX shell script which is not working.
I am running it by KornShell (ksh).
echo $?;
if [ $? -ne 0 ]
then
failed $LINENO-2 $5 $6
fi
failed()
{
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
This is giving an error saying Syntax error:then unexpected.. Basically I have to check for the last executed ksh script's highest/last statement's return code and if it is not equal to zero I have to call function failed with the given parameters. I tried putting semicolon before then but that also did not work.
Can you please help?
Edit1: Based on the inputs I changed code. Still the same problem exists.
ksh ../prescript/Pre_process $1 $2 $3
rc=$?;
if [[ $rc -ne 0 ]];then
echo "failed";
exit 1;
Edit2:
It is working for the then part by using double squared brackets. I feel I used code of bash script for ksh. I am facing problem in function call of failed. Please let me know appropriate way of function call in ksh for this example
This looks like bash rather than ksh
failed() {
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
if [[ $? -ne 0 ]]
then
failed $LINENO-2 $5 $6
fi
You need to be careful. The first operation on $? will usually clear it so that your if won't work anyway.
You would be better off using:
rc=$?
echo $rc
if [ $rc -ne 0 ]
:
Other than that, it works fine for me:
$ grep 1 /dev/null
$ if [ $? -ne 0 ]
> then
> echo xx
> fi
xx
$ grep 1 /dev/null
$ echo $?;
1
$ if [ $? -ne 0 ]
> then
> echo yy
> fi
$ _
Note the lack of output in the last one. That's because the echo has sucked up the return value and overwritten it (since the echo was successful).
As an aside, you should let us know which UNIX and which ksh you're actually using. My working version is ksh93 under Ubuntu. Your mileage may vary if you're using a lesser version.
It looks like, from your update, your only problem now is the function call. That's most likely because you're defining it after using it. The script:
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
failed()
{
echo Return code was $1
}
produces:
qq.ksh[6]: failed: not found
while:
failed()
{
echo Return code was $1
}
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
produces
Return code was 1
you are missing semicolons at the end of the lines:
if [ $? -ne 0]; then
# …

Check that a variable is a number in UNIX shell [duplicate]

This question already has answers here:
How do I test if a variable is a number in Bash?
(40 answers)
Closed 1 year ago.
How do I check to see if a variable is a number, or contains a number, in UNIX shell?
if echo $var | egrep -q '^[0-9]+$'; then
# $var is a number
else
# $var is not a number
fi
Shell variables have no type, so the simplest way is to use the return type test command:
if [ $var -eq $var 2> /dev/null ]; then ...
(Or else parse it with a regexp)
No forks, no pipes. Pure POSIX shell:
case $var in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
(Assumes number := a string of digits). If you want to allow signed numbers with a single leading - or + as well, strip the optional sign like this:
case ${var#[-+]} in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
In either ksh93 or bash with the extglob option enabled:
if [[ $var == +([0-9]) ]]; then ...
Here's a version using only the features available in a bare-bones shell (ie it'd work in sh), and with one less process than using grep:
if expr "$var" : '[0-9][0-9]*$'>/dev/null; then
echo yes
else
echo no
fi
This checks that the $var represents only an integer; adjust the regexp to taste, and note that the expr regexp argument is implicitly anchored at the beginning.
This can be checked using regular expression.
###
echo $var|egrep '^[0-9]+$'
if [ $? -eq 0 ]; then
echo "$var is a number"
else
echo "$var is not a number"
fi
I'm kind of newbee on shell programming so I try to find out most easy and readable
It will just check the var is greater or same as 0
I think it's nice way to choose parameters... may be not what ever... :
if [ $var -ge 0 2>/dev/null ] ; then ...
INTEGER
if echo "$var" | egrep -q '^\-?[0-9]+$'; then
echo "$var is an integer"
else
echo "$var is not an integer"
fi
tests (with var=2 etc.):
2 is an integer
-2 is an integer
2.5 is not an integer
2b is not an integer
NUMBER
if echo "$var" | egrep -q '^\-?[0-9]*\.?[0-9]+$'; then
echo "$var is a number"
else
echo "$var is not a number"
fi
tests (with var=2 etc.):
2 is a number
-2 is a number
-2.6 is a number
-2.c6 is not a number
2. is not a number
2.0 is a number
if echo $var | egrep -q '^[0-9]+$'
Actually this does not work if var is multiline.
ie
var="123
qwer"
Especially if var comes from a file :
var=`cat var.txt`
This is the simplest :
if [ "$var" -eq "$var" ] 2> /dev/null
then echo yes
else echo no
fi
Here is the test without any regular expressions (tcsh code):
Create a file checknumber:
#! /usr/bin/env tcsh
if ( "$*" == "0" ) then
exit 0 # number
else
((echo "$*" | bc) > /tmp/tmp.txt) >& /dev/null
set tmp = `cat /tmp/tmp.txt`
rm -f /tmp/tmp/txt
if ( "$tmp" == "" || $tmp == 0 ) then
exit 1 # not a number
else
exit 0 # number
endif
endif
and run
chmod +x checknumber
Use
checknumber -3.45
and you'll got the result as errorlevel ($?).
You can optimise it easily.
( test ! -z "$num" && test "$num" -eq "$num" 2> /dev/null ) && {
# $num is a number
}
You can do that with simple test command.
$ test ab -eq 1 >/dev/null 2>&1
$ echo $?
2
$ test 21 -eq 1 >/dev/null 2>&1
$ echo $?
1
$ test 1 -eq 1 >/dev/null 2>&1
$ echo $?
0
So if the exit status is either 0 or 1 then it is a integer , but if the exis status is 2 then it is not a number.
a=123
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
numeric
a=12s3
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
ng
Taking the value from Command line and showing THE INPUT IS DECIMAL/NON-DECIMAL and NUMBER or not:
NUMBER=$1
IsDecimal=`echo "$NUMBER" | grep "\."`
if [ -n "$IsDecimal" ]
then
echo "$NUMBER is Decimal"
var1=`echo "$NUMBER" | cut -d"." -f1`
var2=`echo "$NUMBER" | cut -d"." -f2`
Digit1=`echo "$var1" | egrep '^-[0-9]+$'`
Digit2=`echo "$var1" | egrep '^[0-9]+$'`
Digit3=`echo "$var2" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
elif [ -n "$Digit2" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
else
echo "$NUMBER is not Decimal"
Digit1=`echo "$NUMBER" | egrep '^-[0-9]+$'`
Digit2=`echo "$NUMBER" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] || [ -n "$Digit2" ]; then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
fi

Resources