28

I am expecting to use the below variable in my bash script but in case if this is empty or null what would be the best way to handle it and exit from script.

tag=$1  

I am seeing answers with 'set -u'. I know this will work but is this good for production environment?

3
  • 1
    mywiki.wooledge.org/BashGuide/… Commented Jul 1, 2015 at 14:37
  • Should a variable consisting of whitespaces only like this: var=" " be considered empty or not? Commented Jul 1, 2015 at 15:08
  • yes, variable consisting of whitespaces, considered empty. basically, I am thinking to put a check like if [[ ! -z "${Tag}" && "${Tag}" != ’’ ]] for this. Commented Jul 1, 2015 at 15:47

7 Answers 7

43

There is a built-in operator for requiring that a variable is set. This will cause the script to exit if it isn't.

tag=${1?Need a value}

Commonly this is used with the : no-op near the beginning of the script.

: ${1?Need a value}

The conflation of "unset or empty" is somewhat different. There is no similar construct for exiting on an empty but set value, but you can easily use the related syntax ${var:-default} which expands to $var if it is set and nonempty, and default otherwise. There is also ${var-default} which only produces default if the variable is properly unset.

This can be particularly useful when you want to use set -u but need to cope with a possibly unset variable:

case ${var-} in '') echo "$0: Need a value in var" >&2; exit 1;; esac

I somewhat prefer case over if [ "${var-}" = '' ], mainly because it saves me from having to wrap double quotes around ${var-}, and the pesky case of a value in $var which gets interpreted as an option to [ and gives you an error message when you least expect it. (In Bash, [[ doesn't have these problems; but I prefer to stick to POSIX shell when I can.)

Sign up to request clarification or add additional context in comments.

Comments

23

If you want to test that a variable is non-empty, you can do this:

if [ -z "$tag" ]; then
    echo "variable tag is empty so program will exit now!"
    exit 1
fi

From the manual for test:

-z STRING

the length of STRING is zero

Given that you are using the positional arguments to the script, you could also test the number of arguments you receive by looking at $#.

1 Comment

You need quotes around "$tag" or this fails on an empty string (try it and see).
11

No one suggested :? option.

If you want to make sure the variable is set and not null:

SEARCH_PATH=${DAYS_TO_KEEP:?Must provide DAYS_TO_KEEP.}

Will exit immediately with code 2 & print a message:

/entrypoint.sh: line 17: SEARCH_PATH: Must provide DAYS_TO_KEEP.

3 Comments

This exits with a 1 for me on Ubuntu. Also, what's the difference between this and the accepted answer by tripleee?
As mentioned above, It's a different option for users to use to make sure the variable exists and not null.
So the only difference here is that yours also checks null-ness? And the accepted answer doesn't check null-ness? That's pretty awesome! I'd make that distinction more clear (in your answer) in order to more strongly differentiate yours from the accepted one :slightly_smiling_face:
4

I am not sure whether you want to detect if a variable is unset or empty. These are 2 different things. Specifically, a variable can be set but be empty:

$ var=""
$ if [ -z "$var" ]; then echo empty; fi
$ empty

The same is going on here:

#!/usr/bin/env bash

set -u
echo $1

Test:

$ ./test.sh
./test.sh: line 4: $1: unbound variable
$ ./test.sh ""

$

Or here:

#!/usr/bin/env bash

tag=${1?Need a value}
echo $tag

Test:

$ ./se.sh
./se.sh: line 3: 1: Need a value
$ ./se.sh ""

$

Other posters have presented correct ways to detect an unset and empty variable. Personally I like this way of detecting empty and unset variables:

#!/usr/bin/env bash

if [ "$1"A = A ]
then
    echo variable is empty or unset
fi

Test:

$ ./empty.sh ""
variable is empty or unset
$ ./empty.sh
variable is empty or unset
$ ./empty.sh 1
$

2 Comments

The "$1"A method is unnecessary in any remotely modern shell implementation. That was a hack necessary for old shells that couldn't handle explicitly empty arguments for the test command. [ "$1" = "" ] can handle an empty/unset $1 just as well.
It is not necessary, but still, I just like. It's the matter of personal preference.
1

Use pattern matching to detect if the value consists only of whitespace:

pattern=$'*( |\t)'
if [[ $1 = $pattern ]]; then
    echo "First parameter has no non-whitespace characters"
    exit 1
fi

The $'...' quoting makes it easier to add a tab to the string. The extended pattern *(...) matches 0 or more the patterns inside the parentheses (similar to regex ( |\t)*). The pattern is assigned to a variable because = performs exact string matching if any part of its right-hand operand is quoted, so we perform the quoting beforehand to make it easier to set the value.

2 Comments

You need to enable extended globbing for this to work, don't you?
Maybe. Newer versions of bash (4.2 and later?) temporarily turn extended globbing on inside [[... ]] so there is no need to do so explicitly. Otherwise, yes, shopt -s extglob is needed.
1

I rather liked how Perl uses "die" and it's easy to do something similar in shell.

# Print (optional) error message and exit
# Usage: die [[msg] exit_status]
die() {
    [[ -n "$1" ]] && echo "$1"
    [[ -n "$2" ]] && exit $2 || exit 1
}

[[ -n "$tag" ]] || die "Need a tag argument.  Use $0 --help for details"

This assumes bash or Korn shell, but can be converted to classic Bourne shell by changing [[]] to [].

Comments

0

The following test ensure that a variable is either Null or has a value assigned to it.The double quotes are very important and must be used!

VAL= # Creates a NULL variable
if [[ -z "$VAL" && "$VAL" = ’’ ]]
then
echo "The VAL variable is NULL"
fi
or
VAL=25
if [[ ! -z "$VAL" && "$VAL" != ’’ ]]
then
echo "The VAL variable is NOT NULL"
fi

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.