1

I see many times in the shell scripts that they use "_" in the if comparison as indicated below:

if [ "_$str" = "_" ]; then ....; fi

the above code check if the str variable is empty with the comparison if [ "_$str" = "_" ].

Why do not use if [ "$str" = "" ]? why adding "_" in both strings?

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • It seems a good way to skip empty strings comparison. Appending a character in both strings avoids edge cases and keeps the results. – fedorqui Sep 17 '13 at 13:11
  • Simply use `[ -z "${str}" ]`. – devnull Sep 17 '13 at 13:21
  • possible duplicate of [bash test for empty string with X""](http://stackoverflow.com/questions/6852612/bash-test-for-empty-string-with-x) – devnull Sep 17 '13 at 13:33
  • @devnull Interestingly, that command would succeed indirectly in affected shells. If `$str` were empty, the expansion would be incorrectly removed, leaving `[ -z ]`. That, however, might be treated as a non-empty string (not the operator `-z`), which would evaluate as true anyway. – chepner Sep 17 '13 at 13:34
  • possible duplicate of [Why do shell script comparisons often use x$VAR = xyes?](http://stackoverflow.com/questions/174119/why-do-shell-script-comparisons-often-use-xvar-xyes) – oberlies Apr 16 '14 at 13:36

3 Answers3

11

As far as I know it is for historical reasons. There once were (and maybe on some obscure systems still are) shells which had (have) trouble handling empty strings (and maybe strings starting with dashes). Hence the simple idea to prevent empty strings (and option-like looking ones) altogether by adding a prefix. All common shells today do not have these problems anymore.

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • That's what I heard as a reason when I saw this first around 1992. So probably today it is for ancient or prehistoric reasons. – Alfe Sep 17 '13 at 13:22
2

I can only guess that before learning how to use quotes properly, the writers of the scripts you've seen had trouble with something like

if [[ $str = "" ]]; then ....

which will fail if $str is empty, as the argument expands to nothing. Whereas

if [[ _$str = _ ]]

will work, but is a kludge.

rojomoke
  • 3,765
  • 2
  • 21
  • 30
  • The problem predates the `[[...]]` expression in `bash` (which handles expansions of null-valued parameters fine), and was in fact a real bug in the handling of quoted, null-valued parameters by the `test` command in the old Bourne shell. – chepner Sep 17 '13 at 13:27
1

Remember that [ is an alias to the command test. The question is what would happen if your string started with a dash?

In old versions of test when using the standard Bourne shell, you'd get an error:

$ test -gt = "some_string"
invalid argument

The same thing would happen with an if

$ string="-gt"
$ if [ "$string" = "some_other_string" ]
> then
> echo "Match"
> else
> echo "No Match"
> fi
if: invalid argument

That's because the test command would see the parameter with a dash and assume that it's a command argument, then either it's an invalid command argument, or the format of the command is incorrect. If you use [[ instead of [, it's not an issue at all because [[ is a built in test for the if.

This is no longer an issue. The [ and test are internal commands to both the Kornshell and BASH, and these shells can handle this issue. Even the newer versions of test are no longer thrown:

$ test -gt = "some_string"  # No error.
$ echo $?
1

However, older scripts, and those people who either learned from an older timer, or were back writing scripts when system with 32 Mb of memory running on a 16 Mhz 386 chip with Xenix was a state of the art system have gotten into the habit. I use to use x:

if [ x$var = x$foo ]
Alfe
  • 56,346
  • 20
  • 107
  • 159
David W.
  • 105,218
  • 39
  • 216
  • 337
  • +1 for hinting on problems with arguments starting with a dash (so not only empty strings might pose a problem). – Alfe Sep 18 '13 at 08:02
  • @Alfe If you surround the string with quotes, it's not an issue. That is `[ "$foo" = "$bar" ]` is fine even if one or the other variable is empty. However, it is a problem without quotes. `[ $foo = $bar ]` can cause problems. – David W. Sep 18 '13 at 13:11
  • Forgetting the quotes always was and still is a problem. That prefix thing which is the topic here is independent from correct quoting. – Alfe Sep 18 '13 at 13:38