help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Simple echo is printing the wrong value


From: Greg Wooledge
Subject: Re: [Help-bash] Simple echo is printing the wrong value
Date: Wed, 4 Apr 2012 11:09:16 -0400
User-agent: Mutt/1.4.2.3i

On Wed, Apr 04, 2012 at 08:54:25AM -0600, Bill Gradwohl wrote:
> for file in *; do
>    echo ${file}
>    func ${file}

This is already wrong.  QUOTES.  THEY ARE NOT OPTIONAL.

echo "$file"
func "$file"

>    case ${file} in

Now, here you can omit the quotes, because case is one of those places
with special parser rules.

>       '*')
>        echo got asterisk
>       ;;
>       *)
>        echo got something else
>       ;;
>    esac

That case statement looks OK to me.

>    echo "${file}"
>    func "${file}"
>    case "${file}" in
>       '*')
>        echo got asterisk
>       ;;
>       *)
>        echo got something else
>       ;;
>    esac

That one is identical, except that you fixed the echo and the func.

> case '* X' in
>    '*')
>     echo got asterisk
>    ;;

You will NEVER match a literal asterisk here, because you have at least
one asterisk plus one space in the word after case, no matter what X is.
Even if X was intended to be $file.

>    *)
>     echo got something else
>    ;;
> esac

> The for loop sees an unquoted asterisk so that expands to the files in the
> directory = 'x' 'X'

Um, no...
> touch '*'
> touch 'X'

> The for loop therefore has 2 elements in the list to work on, the first
> being *.

Right.

> Bash provides the value of file which is an asterisk to the echo statement.

You mean the unquoted echo, which is totally wrong?  Do not write code
that is totally wrong.  Then you won't have to waste your time on the
semantics of your broken code.

> The echo sees an unquoted asterisk, so Bash expands the * to '*' and 'X'
> again, and the output confirms that.

More correctly, given this block of code:

file=*
echo $file

Bash performs parameter expansion first, and therefore $file becomes *.
Bash performs filename expansion second, and therefore * becomes * X.
The two resulting words * X are passed as arguments to echo.  Echo doesn't
perform its own expansion.  Both of the expansions are done by bash,
before echo is even born.

Of course, that code is broken and wrong, so you should not WRITE that
code.

> The case statement obviously only sees the * as a literal. Why?

Because case is maaaaagic.  It's like [[.  It has its own special rules,
and lets you omit the quotes.

> Why do some things get 2 cracks at expansion and others only 1?

Because that's how it works.  case does not perform filename expansion
on the word following case.

If it helps to think of it this way: the word following case has to stay
ONE WORD.  You can't have multiple words there, because it wouldn't make
any sense, just like the right-hand-side of an assignment can only have
one word.  Filename expansion would produce multiple words, so it isn't
done in either of those two places.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]