Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do shell script comparisons often use x$VAR = xyes?

I see this often in the build scripts of projects that use autotools (autoconf, automake). When somebody wants to check the value of a shell variable, they frequently use this idiom:

if test "x$SHELL_VAR" = "xyes"; then ... 

What is the advantage to this over simply checking the value like this:

if test $SHELL_VAR = "yes"; then ... 

I figure there must be some reason that I see this so often, but I can't figure out what it is.

like image 271
jonner Avatar asked Oct 06 '08 12:10

jonner


People also ask

What does X mean in shell script?

Bash Shell -x Option. Invoking a Bash shell with the -x option causes each shell command to be printed before it is executed.

What does $() mean in shell script?

$() – the command substitution. ${} – the parameter substitution/variable expansion.

Why we use $? In Unix shell script?

The $? variable represents the exit status of the previous command.

What is the benefit of using environment variables in shell scripts?

Environmental variables are used to pass information into processes that are spawned from the shell. Shell variables are variables that are contained exclusively within the shell in which they were set or defined. They are often used to keep track of ephemeral data, like the current working directory.


2 Answers

If you're using a shell that does simple substitution and the SHELL_VAR variable does not exist (or is blank), then you need to watch out for the edge cases. The following translations will happen:

if test $SHELL_VAR = yes; then        -->  if test = yes; then if test x$SHELL_VAR = xyes; then      -->  if test x = xyes; then 

The first of these will generate an error since the fist argument to test has gone missing. The second does not have that problem.

Your case translates as follows:

if test "x$SHELL_VAR" = "xyes"; then  -->  if test "x" = "xyes"; then 

The x, at least for POSIX-compliant shells, is actually redundant since the quotes ensue that both an empty argument and one containing spaces are interpreted as a single object.

like image 174
paxdiablo Avatar answered Oct 22 '22 07:10

paxdiablo


The other reason that no-one else has yet mentioned is in relation to option processing. If you write:

if [ "$1" = "abc" ]; then ... 

and $1 has the value '-n', the syntax of the test command is ambiguous; it is not clear what you were testing. The 'x' at the front prevents a leading dash from causing trouble.

You have to be looking at really ancient shells to find one where the test command does not have support for -n or -z; the Version 7 (1978) test command included them. It isn't quite irrelevant - some Version 6 UNIX stuff escaped into BSD, but these days, you'd be extremely hard pressed to find anything that ancient in current use.

Not using double quotes around values is dangerous, as a number of other people pointed out. Indeed, if there's a chance that file names might contain spaces (MacOS X and Windows both encourage that to some extent, and Unix has always supported it, though tools like xargs make it harder), then you should enclose file names in double quotes every time you use them too. Unless you are in charge of the value (e.g. during option handling, and you set the variable to 'no' at startup and 'yes' when a flag is included in the command line) then it is not safe to use unquoted forms of variables until you've proved them safe -- and you may as well do it all the time for many purposes. Or document that your scripts will fail horribly if users attempt to process files with blanks in the names. (And there are other characters to worry about too -- backticks could be rather nasty too, for instance.)

like image 26
Jonathan Leffler Avatar answered Oct 22 '22 08:10

Jonathan Leffler