bug-bash
[Top][All Lists]
Advanced

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

Re: Question on $@ vs $@$@


From: Lawrence Velázquez
Subject: Re: Question on $@ vs $@$@
Date: Sat, 24 Aug 2024 23:49:52 -0400

On Sat, Aug 24, 2024, at 10:08 PM, Steffen Nurpmeso wrote:
> One hopefully last thing in this regard for me,
>
>   c() { echo "$# 1<$1> 2<$2> 3<$3> *<$*> @<$@>"; }

This easily obfuscates the structure of the "$@" expansion.  You'd
be better off with something like this, which prints each positional
parameter as "<...>".

        c() {
                printf '%s *<%s> @' "$#" "$*"
                printf '<%s>' "$@"
                echo
        }


>   set -- a\ b c\ d e\ f
> ..
>   echo 3
>   IFS=
>   c $*
>   c $@
>   c "$*"
>   c "$@"
> ..
>
> gives a diff of
>
>    3
>   -3 1<a b> 2<c d> 3<e f> *<a bc de f> @<a b c d e f>
>   -3 1<a b> 2<c d> 3<e f> *<a bc de f> @<a b c d e f>
>   +1 1<a bc de f> 2<> 3<> *<a bc de f> @<a bc de f>
>   +1 1<a bc de f> 2<> 3<> *<a bc de f> @<a bc de f>
>    1 1<a bc de f> 2<> 3<> *<a bc de f> @<a bc de f>
>    3 1<a b> 2<c d> 3<e f> *<a bc de f> @<a b c d e f>
>
> So here the unquoted $* is expanded with $IFS=NUL, the variable $*
> was resolved to the string "a bc de f" because the first character
> of $IFS is NUL; this string gets the word split, but since no
> character of $IFS ever matches (but the terminating NUL), no split
> occurs.  How is the shell capable to reconstruct the original
> parameters "a b", "c d", and "e f", as there is no field
> separator.
> (The only thinkable answer is that the step that my MUA does,
> namely resolving $* as a single string first, does not happen,
> right?  I really have to carefully read the standard on Monday.)

Correct.  Since you're using $* unquoted in a context where field
splitting is performed, the shell does not expand it to a single
field.

The bash manual says [1]:

        *
                ($*)  Expands to the positional parameters, starting
                from one.  When the expansion is not within double
                quotes, each positional parameter expands to a
                separate word.  In contexts where it is performed,
                those words are subject to further word splitting
                and filename expansion.  When the expansion occurs
                within double quotes, it expands to a single word
                with the value of each parameter separated by the
                first character of the IFS special variable.  That
                is, "$*" is equivalent to "$1c$2c", where c is the
                first character of the value of the IFS variable.
                If IFS is unset, the parameters are separated by
                spaces.  If IFS is null, the parameters are joined
                without intervening separators.

POSIX.1-2024 says [2]:

        *
                Expands to the positional parameters, starting from
                one, initially producing one field for each positional
                parameter that is set.  When the expansion occurs
                in a context where field splitting will be performed,
                any empty fields may be discarded and each of the
                non-empty fields shall be further split as described
                in 2.6.5 Field Splitting.  When the expansion occurs
                in a context where field splitting will not be
                performed, the initial fields shall be joined to
                form a single field with the value of each parameter
                separated by the first character of the IFS variable
                if IFS contains at least one character, or separated
                by a <space> if IFS is unset, or with no separation
                if IFS is set to a null string.

[1]: 
https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_002a
[2]: 
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_05_02

-- 
vq



reply via email to

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