I need to check the existence of an input argument. I have the following script
if [ "1ドル" -gt "-1" ]
then echo hi
fi
I get
[: : integer expression expected
How do I check the input argument1 first to see if it exists?
-
You did not tell us how you invoked this script. most likely, the first parameter was not an integral number.user1934428– user19344282023年07月03日 10:46:53 +00:00Commented Jul 3, 2023 at 10:46
-
How do I check the input argument1 first to see if it exists? : Do you mean "how do I check whether the argument 1 is non-empty?" or do you mean "how do I check whether the number of arguments is greater than zero?". Please clarify this in your question.user1934428– user19344282023年07月03日 10:48:45 +00:00Commented Jul 3, 2023 at 10:48
12 Answers 12
It is:
if [ $# -eq 0 ]
then
echo "No arguments supplied"
fi
The $#
variable will tell you the number of input arguments the script was passed.
Or you can check if an argument is an empty string or not like:
if [ -z "1ドル" ]
then
echo "No argument supplied"
fi
The -z
switch will test if the expansion of "1ドル"
is a null string or not. If it is a null string then the body is executed.
16 Comments
[ -z "1ドル" ] && echo "No argument supplied"
I prefer one-liners, as they are easier for me; and it's also faster to check exit value, compared to using if
exit 1
at the end of your echos inside the if block when the argument is required for the script to function. Obvious, but worth noting for completeness.programname "" secondarg third
. The $#
check unambiguously checks the number of arguments.if [ ! -z "1ドル" ]; then ...
It is better to demonstrate this way
if [[ $# -eq 0 ]] ; then
echo 'some message'
exit 1
fi
You normally need to exit if you have too few arguments.
4 Comments
[[
is normally more reasonable than [
.return 1
was a better choice (as exit 1
will close the terminal).>&2 echo 'some message'
In some cases you need to check whether the user passed an argument to the script and if not, fall back to a default value. Like in the script below:
scale=${2:-1}
emulator @1ドル -scale $scale
Here if the user hasn't passed scale
as a 2nd parameter, I launch Android emulator with -scale 1
by default. ${varname:-word}
is an expansion operator. There are other expansion operators as well:
${varname:=word}
which sets the undefinedvarname
instead of returning theword
value;${varname:?message}
which either returnsvarname
if it's defined and is not null or prints themessage
and aborts the script (like the first example);${varname:+word}
which returnsword
only ifvarname
is defined and is not null; returns null otherwise.
3 Comments
${varname?message}
. Is the extra :
a typo, or does it change behavior?: ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
sitelog
the show me nginx log file, I want to pass to it argument like sitelog -c
to clear log file.Try:
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "No arguments supplied"
else
echo "Hello world"
fi
6 Comments
$#
and 0
?else
, too.foo*
) and word splitting (i.e. splitting the contents if the value contains whitespace). In this case it's not necessary to quote $#
because both of those cases do not apply. Quoting the 0
is also not necessary, but some people prefer to quote values since they are really strings and that makes it more explicit.Only because there's a more base point to point out I'll add that you can simply test your string is null:
if [ "1ドル" ]; then
echo yes
else
echo no
fi
Likewise if you're expecting arg count just test your last:
if [ "3ドル" ]; then
echo has args correct or not
else
echo fixme
fi
and so on with any arg or var
1 Comment
if [ "${3+set}" ]; then...
to check for at least 3 args, working correctly even if they 3rd arg is empty.Another way to detect if arguments were passed to the script:
((!$#)) && echo No arguments supplied!
Note that (( expr ))
causes the expression to be evaluated as per rules of Shell Arithmetic.
In order to exit in the absence of any arguments, one can say:
((!$#)) && echo No arguments supplied! && exit 1
Another (analogous) way to say the above would be:
let $# || echo No arguments supplied
let $# || { echo No arguments supplied; exit 1; } # Exit if no arguments!
help let
says:
let: let arg [arg ...]
Evaluate arithmetic expressions. ... Exit Status: If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.
4 Comments
exit
which kills my zsh process, I use return
which does not kill it((!$#))
trigger history substitution?-ss
parameter as 3rd argument on my script, if that arg
not presented the clip won't be cut. if [ -z "3ドル" ]; thenI often use this snippet for simple scripts:
#!/bin/bash
if [ -z "1ドル" ]; then
echo -e "\nPlease call '0ドル <argument>' to run this command!\n"
exit 1
fi
Using double square-bracket is always a good practice
#!/bin/bash
if [[ $# -gt 0 ]]; then
echo "Get arguments: $@"
else
echo "No arguments were provided."
fi
$#
returns number of arguments.$@
returns the actual arguments.
You can safely use [[ ... ]]
in most cases, unless you specifically need to use #!/bin/sh
.
In this case, double [[ ... ]]
or single [ ... ]
square bracket makes no difference.
TL;DR
But [[ ... ]]
allows you to:
- Escape special characters like
<
,>
, and|
. - Use regular expressions for string matching.
- Use logical operators
&&
and||
within the brackets.
Let's consider you want pass a text file:
# This works:
if [[ 1ドル == *.txt ]]; then
echo "From double: 1ドル"
fi
# This won't!
if [ 1ドル == *.txt ]; then
echo "From single: 1ドル"
fi
3 Comments
[[
is a non-POSIX extension keyword that is available only in certain shells. It's been in ksh
, bash
, and zsh
since last century, but availability in other shells is still spotty. For example, on my system ash
and dash
both say [[: not found
.If you'd like to check if the argument exists, you can check if the # of arguments is greater than or equal to your target argument number.
The following script demonstrates how this works
test.sh
#!/usr/bin/env bash
if [ $# -ge 3 ]
then
echo script has at least 3 arguments
fi
produces the following output
$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments
Comments
As a small reminder, the numeric test operators in Bash only work on integers (-eq
, -lt
, -ge
, etc.)
I like to ensure my $vars are ints by
var=$(( var + 0 ))
before I test them, just to defend against the "[: integer arg required" error.
2 Comments
var=$(printf "%.0f" "$var")
can handle floats but suffers from the non-zero exit when given a string. If you don't mind an awk, this method I use seems to be the most robust for enforcing an integer: var=$(<<<"$var" awk '{printf "%.0f", 0ドル}')
. If var is unset, it defaults to "0". If var is a float, it is rounded to the nearest integer. Negative values are also fine to use.+0
does not serve any purpose in that expression. Perhaps you were thinking of $(( $var +0 ))
which is more portable. The point of the +0
is so that it will still work when $var
is empty, but if you write $(( var ))
then it is the arithmetic engine that's fetching the value of var
and then evaluating that as a subexpression, so in $((var+0)
the subexpression has already succeeded or failed before the +0
is attempted. In fact, bash
guarantees that $((var))
will evaluate to 0
when var
is empty, whereas leaving out the $
before var
is a syntax error in ksh
.one liner bash function validation
myFunction() {
: ${1?"forgot to supply an argument"}
if [ "1ドル" -gt "-1" ]; then
echo hi
fi
}
add function name and usage
myFunction() {
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"}
if [ "1ドル" -gt "-1" ]; then
echo hi
fi
}
add validation to check if integer
to add additional validation, for example to check to see if the argument passed is an integer, modify the validation one liner to call a validation function:
: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"} && validateIntegers 1ドル || die "Must supply an integer!"
then, construct a validation function that validates the argument, returning 0 on success, 1 on failure and a die function that aborts script on failure
validateIntegers() {
if ! [[ "1ドル" =~ ^[0-9]+$ ]]; then
return 1 # failure
fi
return 0 #success
}
die() { echo "$*" 1>&2 ; exit 1; }
Even simpler - just use set -u
set -u
makes sure that every referenced variable is set when its used, so just set it and forget it
myFunction() {
set -u
if [ "1ドル" -gt "-1" ]; then
echo hi
fi
}
Comments
In my case (with 7 arguments) the only working solution is to check if the last argument exists:
if [[ "7ドル" == '' ]] ; then
echo "error"
exit
fi
3 Comments
7ドル
is the 7th argument (8th if you count 0ドル
which is the script name), so this does not check if the last argument exists, it checks if the 7th argument exists.exit
without exit status will return the exit status of echo "error"
, which I expect to be zero. Recommend shellcheck
and set -euo pipefail
. I'm going to stop now...