bug-bash
[Top][All Lists]
Advanced

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

Re: Document that here strings don't support brace expansion.


From: alex xmb ratchev
Subject: Re: Document that here strings don't support brace expansion.
Date: Wed, 15 Mar 2023 09:04:06 +0100

On Wed, Mar 15, 2023, 8:07 AM Robert Elz <kre@munnari.oz.au> wrote:

> While it is probably useful to have every place where expansions occur list
> which ones apply, perhaps it would (also) be useful to include the general
> principle which controls all of this.
>
> That is, expansions are performed, late (just as commands are about to
> be run, after all parsing has finished, etc) in one of two basic contexts.
>
> In one, like in arg lists to commands (also the list after "in" in a for
> statement, and probablty more places I have forgotten), any number of words
> can be produced.  In those, all the expansions typically happen.
>
> In the other, exactly one word is required - like the word in var=${word}
> or the word in case ${word} in, or (in bash, and perhaps a couple of other
> shells) the word after a here string operator <<<${word} (and one more I
> will come to in a minute).   [The word after a here-doc redirect operator
> (<<)
> is strange for hysterical (oops: historical) reasons.]
>
> In those, the syntax allows for only one word to be produced, so performing
> field splitting, globbing, or brace expansion, all make no sense at all,
> and so the basic assumption, unless specified otherwise, is that none of
> those will happen.  (This is also why var="$@" is just plain stupid to
> write,
> and has unspecified consequences, though people keep doing it).
>
> quote removal always happens (everywhere).
>
> The one other place where just one word is required, and is all that
> makes sense, is after a redirect operator - the file name (or fd if the
> operator is >& or similar).   That is >${word} (etc).   For most shells
> none of the multi-word generating "expansions" happen there either, as
> there has to be exactly one filename to write into (in this example), not
> several.   However, at least when interactive, some shells perform globbing
> at this point, but require that only a single filename match the pattern
> (making it an error if more than one do) - just because users are too lazy
> to type the entire filename -- or use a func like:
>
>         setfn()
>         {
>                 var=$1; shift
>                 set -- "$@"
>                 case "$#" in
>                 1) test -e "$1" && {
>                         eval "$var='$1'"
>
declare -g "$var=$1"

>                         return 0
>                    }
>                    printf >&2 'No match\n'
>                    return 1;
>                    ;;
>                 esac
>                 printf >&2 'Ambiguous: %d files matched\n', "$#"
>                 return 1
>         }
>
> Used like
>         setfn f a*.txt
> after which, if it worked, you can use "$f" instead of the
> filename you are too lazy to type, which is shorter than a
> pattern guaranteed to only match one file will often be.
>
> Further it doesn't risk failing later, if something you do
> causes the pattern to later match more than one file (say you
> create abc-new.txt as a new version of abc.txt or save the
> old one as abc.was.txt).   "$f" doesn't change until you change it.
>
> Bash allows filename expansion after a redirect, at least in
> interactive shells (haven't tested it for non-interactive), it
> also performs brace expansion there - but that's largely guaranteed
> to fail, so I have no idea why - no field splitting though.
> Those exceptions to the general rule need to be clearly pointed out,
> but explaining every time something requires just one word, that
> some expansions don't happen, when in a context where it would be
> insane if they did, seems overdone.
>
> <<< requires a single word, as so all other redirect operators.
> Brace expansion, which has as its whole purpose, generating multiple
> words (as does field splitting, though it doesn't always succeed)
> (globbing merely can) should be obviously inappropriate there (just as
> it really should be after any redirect operator, which is why I
> was surprised to see
>
>         $ cat < a{1,2,3}
>         -bash: a{1,2,3}: ambiguous redirect
>
> rather than something more like
>         -bash: a{1,2,3}: No such file or directory
>
> The only example of brace expansion actually "working" in a
> redirect, is something like
>
>         $ cat <a{1..1}
>         -bash: a1: No such file or directory
>
> but I am unable to think of any situation where doing that is
> better than just "cat <a1".   Even if the 1's were variables being
> expanded, we know that either they have the same value, in which
> case we only need to use one of them <a${var}  or they're different,
> in which case we get an "ambiguous redirect error".   Crazy.
>
> kre
>
>
>


reply via email to

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