3

I can see in unix shell scripts that following construction used

[ x"$VAR" = x"VALUE" ] 

instead of

[ "$VAR" = "VALUE" ] 

Why?

Volodymyr Bezuglyy
  • 16,295
  • 33
  • 103
  • 133
  • Appears to be mostly a duplicate of http://stackoverflow.com/questions/174119/why-do-shell-script-comparisons-often-use-xvar-xyes – Frerich Raabe Jun 22 '10 at 13:55
  • 1
    If you're using a modern shell, quoting is sufficient. Using "x" is an archaic technique which is no longer needed. – Dennis Williamson Jun 22 '10 at 15:02
  • ...and that's true for a *very* loose definition of "modern"; the `x"$foo"` idiom hasn't been useful since at least 1991, so long as one avoids the various `test` usage modes presently marked obsolescent (see the `OB` markers in http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html; these modes are obsolescent *precisely because* they lead to ambiguities where data can be confused for syntax of `test` itself). – Charles Duffy Mar 25 '19 at 02:03

4 Answers4

10

Because shells were not always entirely well-behaved if one of the variables was empty.

Consider if $VAR was empty/null and $VALUE is "foo", your two constructs expand to:

[ x = xfoo ]

and

[ = foo ]

The latter would cause an error in some shells due to being an illegal construct, while the former is valid in any case. This is not a problem in recent version of bash (perhaps even old versions of bash) but that's where it comes from historically - and asides from the occasional moment of puzzlement from people in your situation, there's little reason not to do it for compatibility with a wider range of shells.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 2
    There are quotes in my example. I said [ "x" = x"foo" ] not [ x = xfoo ] – Volodymyr Bezuglyy Jun 22 '10 at 13:41
  • 4
    With quotes (and modern shells), you don't need the 'x' -- `[ "$var" = "val" ]` becomes, when var is empty: `[ "" = "val" ]` which is simply false with no errors. – glenn jackman Jun 22 '10 at 15:02
  • @AndrejDoyle, can you identify a single shell with this bug? Even [heirloom `sh`](http://heirloom.sourceforge.net/sh.html) doesn't have it. The bugs that *are* more readily identifiable don't relate to empty (but correctly-quoted) strings, but to strings containing only `!`, `-a`, `-o`, `(` or `)` being mistaken for `test` syntax. – Charles Duffy Mar 25 '19 at 02:04
4

when $VAR is empty it would give a syntax error [ = "VALUE"], thus the usage of x

knittl
  • 246,190
  • 53
  • 318
  • 364
  • Yup. If you're interested in learning a lot of little things like this in advance, rather than as you stumble across them, I'd personally recommend the O'Reilly book *Classic Shell Scripting*, see http://oreilly.com/catalog/9780596005955 . A lot of the more obscure bits of shell scripts became a lot more comprehensible once I'd read this. – Matt Gibson Jun 22 '10 at 13:30
  • 2
    The OP's code used quotes around the expansions, making this untrue. – Charles Duffy Oct 20 '17 at 19:51
  • @CharlesDuffy: that depends etnirely on which shell is used. See comments on other answers on this question. – knittl Oct 20 '17 at 22:24
  • @knittl, the POSIX sh standard was published in 1991. **Every** compliant shell has the property in question. That there existed shells in the 1970s where quotes didn't make a difference is not just irrelevant today -- it was irrelevant a decade ago, and a decade before that. – Charles Duffy Oct 20 '17 at 22:25
  • @knittl, ...there *are* some undefined cases in the POSIX spec where `"x$foo"` makes a difference, but (1) they don't involve empty strings (rather, they involve cases where *a value being tested* is precisely `(`, `)`, `-a` or `-o`), and (2) they can only happen if `-a` or `-o` is in use to combine multiple operations into a single `test` invocation (syntax which has been marked obsolescent since at least the 2008 release of the standard). – Charles Duffy Oct 20 '17 at 22:29
1

This is an old technique to prevent either side of the comparison from being empty. Some shells don't handle empty strings properly.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
  • @Vladimir: According to http://tldp.org/LDP/abs/html/comparison-ops.html (see the footnote), some older Bash versions don't handle empty strings correctly. – Frerich Raabe Jun 22 '10 at 13:55
  • It's a shame they don't provide enough information in that footnote to permit for reproduction. The ABS does not exactly have a reputation as a source of reliable and trustworthy information; the freenode #bash channel [has been guiding folks away from it](http://wooledge.org/~greybot/meta/abs) at least since 2008. – Charles Duffy Oct 20 '17 at 20:03
0

you have got your explanations, but here's another approach, using case/esac instead of if/else

case "$VAR" in 
  "$VALUE" ) echo 'yes';;
  * ) echo 'no' ;;
esac
ghostdog74
  • 327,991
  • 56
  • 259
  • 343