0

Say I did the following:

IFS=,
x="hello,hi,world"
y=$x

y will have the string hello hi world, so it's like y=$x was replaced by:

y="hello hi world"

Now say I have the following script:

IFS=,
x="hello,hi,world"
if [ $x = "hello hi world" ]
then
    echo "equal"
fi

When running the above script, I get the following error:

test.sh: line 3: [: too many arguments

I assume that I got this error because the statement if [ $x = "hello hi world" ] was replaced by if [ hello hi world = "hello hi world" ] and not by if [ "hello hi world" = "hello hi world" ] upon execution.

So this means that the variable $x was expanded in two different ways depending on the context it was in (one time it was expanded with double quotes, and another time it was expanded without double quotes).

Am I correct?

4 Answers4

4

y will have the string hello hi world

No, it won't. Expansions in variable assignments are not subject to word splitting or filename globbing. (In a sense, they always act like they were double-quoted.) See: When is double-quoting necessary?

$ IFS=,
$ x="hello,hi,world"; y=$x
$ echo "$y"
hello,hi,world

I assume that I got this error because the statement if [ $x = "hello hi world" ] was replaced by if [ hello hi world = "hello hi world" ]

Yes, sort of. It's not a text-based replacement, but since $x was not quoted here, it does go through word splitting, and the [ command sees six distinct arguments (hello, hi, world, =, hello hi world, and ]), not the four it expects.

ilkkachu
  • 138,973
0

Variables indeed behave differently with respect to quoting if they are used in assignments. In

y=$x

no word splitting is performed i.e. it is equivalent to

y="$x"

But in a normal parameter expansion like

if [ $x =

it does make a difference whether there are quotes. BTW: With quotes $x would not have been expanded to "hello hi world" but "hello,hi,world".

Hauke Laging
  • 90,279
0

Word splitting does not happen during variable assignment, so y contains hello,hi,world. However, word splitting does happen inside [], and since you set IFS=, it is expanded to hello hi world as separate words.

The problem is that [ expects a specific number of arguments, and it's telling you it received too many because of the word splitting. Since you tagged this with bash, you can use its superior [[ ]] command to disable word splitting and you won't get the error.

If you actually do want to do word splitting on x, you can do it like this: y="$(IFS=','; echo $x)". That will assign hello hi world as one word to y.

m0dular
  • 1,261
0

You are having quoting issues:

  1. Variable expansion:

    y will have the string hello hi world

    No it won't. But an echo unquoted will print such value:

    $ IFS=,
    $ x="hello,hi,world"
    $ y=$x
    $ echo $y
    hello hi world
    

    Yes, the IFS character (,) splits the variable expansion and echo places an space between the arguments, look at this to see it in detail:

    $ printf '<%s>\n' $y
    <hello>
    <hi>
    <world>
    

    However, a quoted expansion will not be changed by IFS nor split:

    $ echo "$y"
    hello,hi,world
    $ printf '<%s>\n' "$y"
    <hello,hi,world>
    
  2. Test line

    [ $x = "hello hi world" ]
    

    The same quoting problem happens here, the variable gets expanded and split into words. The line becomes:

    [ hello hi world = "hello hi world" ]
    

    The three arguments "hello", "hi" and "world" can not be parsed into a correct test construct.

    This, however, does:

    $ y=hello,=,world,-o,hello
    $ [ $y = "hello" ] && echo yes || echo no
    yes
    

    because what got executed was:

    [ hello = world -o hello = "hello" ] && echo yes || echo no
    

    Quoting avoids the splitting:

    $ y=hello,hi,world
    $ [ "$y" = "hello,hi,world" ] && echo yes || echo no
    yes
    

    As using the [[ construct also avoids splitting:

    $ y=hello,hi,world
    $ [[ $y == "hello,hi,world" ]] && echo yes || echo no
    yes
    
  3. Your question:

    Am I correct?

    No, each time the variable got expanded in the same way.

TL;DR

Quote your expansions.