How to test empty input? - jq

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

Related

Exit with non-zero if input is empty

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

test ./script.sh doit test dont show true output

#!/usr/bin/env zsh
doit() {
if [[ "$1" = "start" ]]; then
for loc in $(cat all-doc); do
if ! screen -list | grep -q My-$loc; then
screen -dmS My-$loc /home/Server -f /home/$loc.cfg
fi
done
elif [[ "$1" = "stop" ]]; then
for loc in $(cat all-doc); do
if screen -list | grep -q My-$loc; then
pkill -f My-$loc;
fi
done
else
echo "Option: ERROR..."
fi
}
nothing() {
if [[ "$1" = "start" ]]; then
echo "Option: 1"
elif [[ "$1" = "stop" ]]; then
echo "Option: 2"
else
echo "Option: 3"
fi
}
case "$2" in
start)
"$1" "$2";
;;
stop)
"$1" "$2";
;;
restart)
restart;
;;
*)
echo "Usage: $0 {doit|nothing} {start|stop|restart}"
exit 1
;;
esac
exit 0
Output:
./script.sh:34> case test (start)
./script.sh:34> case test (stop)
./script.sh:34> case test (restart)
./script.sh:34> case test (*)
./script.sh:45> echo 'Usage: ./script.sh {start|stop|restart}'
sage: ./script.sh {start|stop|restart}
./script.sh:46> exit 1
this script for start and stop and restart my servers.
If $2 not match with "start" "stop" "restart" in both function must call else but not work.
Ok question is why ./script.sh doit test did not call
else
echo "Option: ERROR..."
whats the sulotion ? Is there better way to do somthing for ./script.sh $1 $2 i mean $1 get function and $2 get start|stop|restart ?

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

Case statement is not showing any output

I am trying to execute below script,
data=$(printf "%s " $(find output.log -type f -exec grep 'ACTIVE\| NOT ACTIVE' {} \; | awk '{print $1}'))
status=`find output.log -type f -exec grep 'ACTIVE\| NOT ACTIVE' {} \; | awk '{print $3}'`
case "$data" in
("Instance1")
echo "Status for Instance1 is : $status";
;;
("Instance2")
echo "Status for Instance2 is : $status";
;;
"") echo "empty things"
;;
esac
but it is not showing any output.. maybe i am missing something in my script (may be lot)
The logfile I am using in above script is ie. output.log,
INSTANCE_NAME OPEN_STATUS STATUS
---------------- ------------ -----------------
Instance1 OPEN ACTIVE
Instance2 OPEN NOT ACTIVE
Can anyone tell me what is wrong with above script ?
Thanks,
You don't loop over your entries, thus you never have a data "Instance1" but "Instance1 Instance2".
You probably want something as the following:
items=$(grep -0 'ACTIVE\| NOT ACTIVE' output.log | tr -s ' ' )
IFS=$'\r\n'
for it in $items; do
data=$(echo $it | cut -d ' ' -f1 )
status=$(echo $it | cut -d ' ' -f3- )
case "$data" in
("Instance1")
echo "Status for Instance1 is : $status";
;;
("Instance2")
echo "Status for Instance2 is : $status";
;;
"") echo "empty things"
;;
esac;
done

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