help-bash
[Top][All Lists]
Advanced

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

Re: [Help-bash] Anomalies with ${*}


From: Greg Wooledge
Subject: Re: [Help-bash] Anomalies with ${*}
Date: Tue, 27 Mar 2012 09:31:49 -0400
User-agent: Mutt/1.4.2.3i

On Tue, Mar 27, 2012 at 07:08:05AM -0600, Bill Gradwohl wrote:
> Sorry about not supplying the output I see. I thought running it on your
> end would produce the same thing I see, but maybe that isn't true.

I can run it, yes, but that doesn't tell me what you *thought* it would
do.  And it takes time and effort.

> When abc contains 2 spaces, I can replace them and get a null string with
> the pattern substitution.
> When I replace the abc with *, it no longer works as is evidenced by the
> tests.

Because the substitution is performed on each *individual* parameter,
before concatenating them.

> I have a case where I have from 1 to 3 passed parameters. They could all be
> null strings.

Use the loop I gave in the previous message.

allnull=1
for arg; do if [[ $arg ]]; then allnull=0; break; fi; done

> Here is the simple statement I wanted to write :
> 
> { [ $# -eq 0 ] || [ $# -gt 3 ] || [ "${*// /}" == '' ] ; } && syntax

You also should not use == inside a [ command.  That is a bashism, and
you will get a syntax error in sh.  For that matter, // substitution is
also a bashism.  If you're going to use bashisms, you should go whole hog
and use the [[ and (( commands.

(($# == 0 || $# > 3)) && syntax
allnull=1
for arg; do if [[ $arg ]]; then allnull=0; break; fi; done
((allnull)) && syntax

> Alternatively setting IFS='' when evaluating the ${*} should also produce a
> null string. It doesn't.

Oh, but it does:

imadev:~$ set -- '' '' ''
imadev:~$ IFS=''
imadev:~$ echo "<$*>"
<>
imadev:~$ unset IFS
imadev:~$ 

See?  It's a null string.  If you don't like my loop, you could write it
this way:

(($# == 0 || $# > 3)) && syntax
IFS=''
[[ "$*" ]] || syntax
unset IFS

But I don't think that's better than using the loop.

> I don't see where this is clever or tricky code. Its a simple substitution.
> What else would * be good for if not to aggregate all the parms and then do
> something with the aggregation?

The only times you should be aggregating multiple parameters together are
to present them to a human being, or when they are components of some
larger entity (like octets of an IP or MAC address, or directories in a
single pathname, which for some reason have been split apart previously).

Given this code:

IFS=''
[[ "$*" ]] || syntax
unset IFS

Without any comments or other clues to what it's doing, I would have to
sit and stare at it for several minutes to figure out what it's doing and
whether it's doing it correctly.  That's bad.  Now, with a nice comment
before it, it might be OK....

In general, I consider "concatenate all the positional parameters together
and check the whole resulting string for various symptoms" to be a hack,
unless the resulting string has some actual *meaning* (e.g. it's a pathname
and you concatenated it using /).  Why can't you just iterate over them?



reply via email to

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