[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Running commands as "$@"
From: |
Kerin Millar |
Subject: |
Re: Running commands as "$@" |
Date: |
Thu, 2 Feb 2023 15:18:31 +0000 |
On Thu, 2 Feb 2023 12:11:32 +0100
Cristian Zoicas <zoicas@medialab.sissa.it> wrote:
> Hello all
>
> Let's assume the following script.
>
> # ---- begin script runner.sh ----
> eval "$@"
> # ---- end script runner.sh ----
>
> If we call this script with the following command line
>
> $ sh runner.sh ls -l
>
> the 'ls -l' command will be executed.
>
> Now, if a call the script with the commands
>
> $ sh runner.sh A=B
>
> we get the following errors:
>
> runner.sh: 10: runner.sh: A=B: not found
That's not what happens in any conforming implementation of sh (see below).
> Why the shell does not treat the first string in "$@" ('A=B'
> in these cases) as the first possibile token of command (which
> is an assignemnt)?
Probably because the script that you presented isn't representative of the
issue, in so far as you weren't using eval at the time.
>
> In addition, the problem is NOT solved by using 'eval "$@"'.
> Apparently it works. For example the command
>
> $ sh runner.sh A=BCD
>
> works, but
>
> $ sh runner.sh A="B CD"
>
> gives an error. In this case the error (I think) comes
> from the way the expansion of "$@" is performed: eval has to evaluate the
> string "A=B CD", so it treats A=B as an assignemnt and 'CD' as
> a command.
This is correct.
I think that your questions may be addressed overall by reading
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02.
As concerns potential variable assignments that are the leading words of a
simple command, the parser will only interpret them as such in the case that
each of the applicable tokens contains an <equals-sign> and is not quoted in
any way. Thus, the following examples do not work in the way that you might
have imagined.
$ set -- A=B
$ "$1"
bash: A=B: command not found
$ 'A=B'
bash: A=B: command not found
$ \A=B
bash: A=B: command not found
Conversely, the following example works because the parameter expansion is
performed prior to the resulting word(s) being injected into the tokeniser by
eval. The observed token ends up being A=B, literally.
$ set -- 'A=B'
$ eval "$1"
--
Kerin Millar