1

I want to create an alias called def that takes a varible and checks if it's defined. If it isn't def prints 'the varible is not defined.

3 Answers 3

2

The following function will print an error message if the given the name of a variable that is null or undefined:

def() { : "${!1:? "Variable not defined."}" ; }

Examples:

$ def PATH
$ def NONESUCH
bash: !1:  Variable not defined.

This function requires bash.

Explanation:

The body of the function consists of one command which is given one argument. The command is : which acts like a no-operation. The argument to that command is "${!1:? "Variable not defined."}". In bash, the construct ${!1} returns the value of the variable whose name is given by $1, the first argument to the function. If the variable whose name is $1 is set and not null, then "${!1:? "Variable not defined."}" returns its value. Its value is ignored by : because : is a no-op. If the variable with that name is either unset or null, then, because of the :? parameter expansion construct, the given error message is returned.

Improved Output Format

The above function did not return exactly the message that you asked for. We can fix that:

$ def() { ( : "${!1:? "Variable  not defined."}" ) 2>&1 | sed 's/^bash: !1:  //'; }
$ def NONESUCH
Variable not defined.

Or,

$ def() { ( : "${!1:?}" ) 2>/dev/null || echo "Variable not defined"; }
$ def NONESUCH
Variable not defined
1

Since Ubuntu 12.04 LTS (and perhaps a bit before that, but not as far back as 10.04 LTS), the bash version in Ubuntu has been at least 4.2. Thus it supports the -v operator for the test, [, and [[ builtins.

If you only learn one way to test if variables are defined in bash, it should probably be the parameter expansion technique used in John1024's excellent answer. Even though Ubuntu systems using bash 4.1 and earlier are becoming increasingly uncommon, 10.04 still has limited server support, and earlier versions of bash are much more common on some other GNU/Linux systems (and other Unix-like OSes).

But if you have bash 4.2 or higher, the "improved output format" from John1024's answer can be further simplified to:

def() { [ -v "$1" ] || echo 'Variable not defined'; }

Note that if foo is the name of the variable you're interested in, [ -v foo ]--not [ -v $foo ]--tests if it's defined. In this case, I have $1 because the first positional parameter passed to def will contain the name of the variable to be tested as its value. (The $ in my example achieves the same additional level of indirection achieved by ! in the ${...} expression of John1024's example.)

ek@Ilex:~$ def() { [ -v "$1" ] || echo 'Variable not defined'; }
ek@Ilex:~$ def PATH
ek@Ilex:~$ def NONESUCH
Variable not defined

Both my and John1024's def implementations will print Variable not defined:

  • when no variable by the name passed as the function's first argument exists
  • but also when no first argument is passed to def.

That is:

ek@Ilex:~$ def
Variable not defined

If you'd prefer a separate message in that situation, you can handle the case of def receiving no arguments separately:

def() {
    if [ $# -eq 0 ]; then
        echo 'error: too few arguments' >&2
        return 1
    elif [ ! -v "$1" ]; then
        echo 'Variable not defined'
    fi
}

I've written that based on the idea that having def's first argument exist, whether or not it names a defined variable, is considered normal operation, and not an error. In contrast, passing no arguments to def is an error and I've treated it as such:

  • >&2 sends the output of echo to standard error.

  • return 1 makes def return with nonzero exit status, indicating failure. (This is mainly useful for when a call to def will appear instead a compound statement or script, though the exit status of the last command may also be checked with echo $?.)

    In other cases def will return the default exit status of 0 (unless of course there's some other error, such as echo being unable to write Variable not defined to standard output).

ek@Ilex:~/source$ def NONESUCH
Variable not defined
ek@Ilex:~/source$ def
error: too few arguments
0

According to Advanced Bash-Scripting Guide:

In a script, aliases have very limited usefulness. It would be nice if aliases could assume some of the functionality of the C preprocessor, such as macro expansion, but unfortunately Bash does not expand arguments within the alias body. [117] Moreover, a script fails to expand an alias itself within "compound constructs," such as if/then statements, loops, and functions. An added limitation is that an alias will not expand recursively. Almost invariably, whatever we would like an alias to do could be accomplished much more effectively with a function.

This is why you should follow Eliah Kagan or John1024 answer.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .