help-bash
[Top][All Lists]
Advanced

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

Quoting


From: eduardo-chibas
Subject: Quoting
Date: Wed, 28 Jul 2021 16:16:39 +0200


> Sent: Thursday, July 29, 2021 at 1:48 AM
> From: "Greg Wooledge" <greg@wooledge.org>
> To: help-bash@gnu.org
> Subject: Re: Quoting
>
> On Wed, Jul 28, 2021 at 03:14:07PM +0200, eduardo-chibas@caramail.com wrote:
> > > Sent: Thursday, July 29, 2021 at 1:06 AM
> > > From: "Greg Wooledge" <greg@wooledge.org>
> > > To: help-bash@gnu.org
> > > Subject: Re: Quoting
> > >
> > > On Wed, Jul 28, 2021 at 01:29:45PM +0200, eduardo-chibas@caramail.com 
> > > wrote:
> > > > Is is adequate using the following
> > > >
> > > > : ${fdir:=${@:$#}}
> > > >
> > > > Or is the following better
> > > >
> > > > : ${fdir:="${@:$#}"}
> > >
> > > Are you simply trying to put the *last* argument into a variable?
> >
> > Yes
> >
> > > [[ $fdir ]] || fdir=${!#}
> >
> > I have read long winded discussions on the security implications of not 
> > quoting
> > variables.  Discussions are quite complicated.
>
> Yes, it's an important subject, and some of the rules are a bit obscure.
> I omitted quotes in my answer because they weren't necessary.  Because:
>
> 1) The [[ keyword has special parsing rules.  Word splitting does not
>    occur.  Quotes are only necessary on the right hand side of the =
>    operator if you want to perform a string match rather than a glob
>    match.
>
>    This is unique to the [[ command, which is a bash extension.
>
> 2) On the right hand side of a simple assignment (x=y), you can omit the
>    quotes.  Word splitting does not occur.
>
>    This is standard in all Bourne family/POSIX shells.
>
> The construction that you tried to use is a weird mix of ancient
> convention and bash extensions.  I'm not particularly fond of it, and I
> don't recommend it due to its unreadability.  The fact that you couldn't
> figure out how to write it properly, to the point that you had to ask
> about it, is another reason to avoid it.
>
> If you really want to go down that road, though, you have to tear it
> apart and analyze it piece by piece.
>
> First, you have this thing, which is POSIX standard:
>
> : ${x:=y}
>
> Word splitting is performed here, so ideally you'd want to quote the
> expansion to prevent that.  It's not actually a security risk; more of
> a hygienic practice.
>
> : "${x:=y}"
>
> That's the preferred form for this piece.
>
> Next, you've got this piece on the inside:
>
> "${@:$#}"
>
> This is a variant of "$@".  "$@" is POSIX standard, and it expands to a
> list of zero or more words.  Building from that, you've introduced a
> bash extension, "${@:number}" which says to begin the list at a chosen
> point, so that we have a (potentially) smaller list -- but still a list
> of zero or more words.
>
> Normally, if you wanted to store this list, you'd use an array variable.
>
> However, you've carefully selected the "number" here so that the list is
> always precisely one word long, rather than an arbitrary number of words.
>
> In essence, you are denying the very nature of "$@" as a list.  This is
> one of my objections to this construction.  It's extremely unintuitive.
>
> However, if you insist on using this construction, then the quotes are
> required here.  You need each word (or "the word") to remain intact,
> and not undergo word splitting.
>
> Now, it gets even *more* complicated because you're trying to assign
> this list-that-is-really-just-one-word to a variable within a parameter
> expansion using the arcane := syntax.
>
> You *do* want to keep the quotes.
>
> What you end up with, then, is:
>
> : "${fdir:="${@:$#}"}"
>
> And may the gods help anyone trying to read this script and figure out
> what this line does.

Yes you need all the gods of olympus and some more for that.  Rather than the 
path
to take, it was an introspection on the difficulties introduced by parameter 
expansion
that leads to "${fdir:="${@:$#}"}".  Many get this wrong.

> I prefer  [[ $fdir ]] || fdir=${!#}  because I believe it's much easier
> to understand.  ${!#} is a bash extension for "the last argument", and
> it's shorter and simpler to understand than "${@:$#}" is.

Yes, much easier to understand.  My introspection actually started with 
examining
the `local` declaration for local variables.


> If you prefer to put in the optional quotes, you can do that.
>
> [[ "$fdir" ]] || fdir="${!#}"
>
> works just as well.  Some people feel safer with the optional quotes
> in place, and they don't hurt anything.
>
>



reply via email to

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