0

I know that MyVar="a b" ; [ $MyVar = "a b" ] will signal an error because the resultant expansion is [ a b = "a b" ].

I tried to avoid that case:

$ MyVar="\"a b\""
$ [ $MyVar = "a b" ]
-bash: [: too many arguments

Why did I fail? Didn't it expand to [ "a b" = "a b" ]?


I know there is a [[ ... ]] form; I know I can write "$MyVar".

I am asking why is my approach ineffective.

shynur
  • 334
  • 10
  • try this: MyVar="a b" ; [ "$MyVar" == "a b" ] && echo ok tl;tr; without "" expression evaluates to [ a b == "a b" ] – Vicctor May 07 '23 at 17:56
  • @Vicctor: `==` is not allowed in `POSIX` mode, see my answer – Gilles Quénot May 07 '23 at 18:15
  • 1
    The shell parses quotes and escapes *before* expanding variables, so putting quotes and/or escapes in variables doesn't work -- by the time they're part of the command, it's too late for them to do anything useful. See ["Why does shell ignore quoting characters in arguments passed to it through variables?"](https://stackoverflow.com/questions/12136948/why-does-shell-ignore-quoting-characters-in-arguments-passed-to-it-through-varia) – Gordon Davisson May 07 '23 at 18:17
  • 1
    enable debug mode (`set -xv`) and run your code again to see what `bash` is seeing – markp-fuso May 07 '23 at 19:10
  • 2
    Quotes *in* a parameter are data; quotes *surrounding* a parameter expansion are syntax. – chepner May 07 '23 at 19:19
  • @chepner: Your comment is incisive, how about making it an answer? I’ll upvote for it. – shynur May 08 '23 at 04:42

2 Answers2

1

It's because you encounter shell word splitting: you missed to "quote" the variable.

Learn how to quote properly in shell, it's very important :

"Double quote" every literal that contains spaces/metacharacters and every expansion: "$var", "$(command "$var")", "${array[@]}", "a & b". Use 'single quotes' for code or literal $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. See
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
when-is-double-quoting-necessary

Better use this form in bash, no need to quote:

MyVar="a b" ; [[ $MyVar == "a b" ]]

[[ is a bash keyword similar to (but more powerful than) the [ command. See http://mywiki.wooledge.org/BashFAQ/031 and http://mywiki.wooledge.org/BashGuide/TestsAndConditionals. Unless you're writing for POSIX sh, I recommend [[


If you need to write POSIX code, you need quotes:

MyVar="a b" ; [ "$MyVar" = "a b" ] && echo ok

Note the use of single = operator mandatory for POSIX shell.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
1

why is my approach ineffective.

That's because $MyVar without quotes will be split into "a and b" (two strings) and the == operator only works with one argument on the left hand side and one argument on the right hand side.

Note that parameter expansion is a one-pass thing. It expands the variable $MyVar into "a and b" and does then not reevaluate the result. The order in which the expansions occur is listed in Shell expansion:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and filename expansion.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • So `$MyVar` is split into `"a` and `b"`, and *then* they are inserted into the `test` form? – shynur May 07 '23 at 18:47
  • @shynur Exactly – Ted Lyngmo May 07 '23 at 18:48
  • It would be better if you give *short precise citations/references* and links to corresponding them. Upvote in advance. – shynur May 07 '23 at 18:50
  • @shynur The full chapter on parameter expansion is [here](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html). I'm not sure if it contains exactly what you need but it contains a lot. – Ted Lyngmo May 07 '23 at 18:52
  • I mean, extract the key passages. This saves time for anyone who encounters this problem. It's not very important, so, of course, you can refuse. I'm just suggesting. :-) – shynur May 07 '23 at 18:58
  • @shynur I added a better entry into the documentation at least :) – Ted Lyngmo May 07 '23 at 19:07