Todd A. Jacobs | 3 Dec 16:04 2009

Re: Parameter Expansion

On Thu, Dec 03, 2009 at 10:50:19AM +0530, Kaushal Shriyan wrote:

> Can someone explain me about Parameter Expansion in BASH ? Its really
> difficult to grasp.

If you can provide an example of what you're trying to do, we can help
you figure out what kind of expansion you need and why.

--

-- 
"Oh, look: rocks!"
	-- Doctor Who, "Destiny of the Daleks"
Kaushal Shriyan | 3 Dec 18:06 2009
Picon

Re: Parameter Expansion

On Thu, Dec 3, 2009 at 8:34 PM, Todd A. Jacobs <nospam@...> wrote:
> On Thu, Dec 03, 2009 at 10:50:19AM +0530, Kaushal Shriyan wrote:
>
>> Can someone explain me about Parameter Expansion in BASH ? Its really
>> difficult to grasp.
>
> If you can provide an example of what you're trying to do, we can help
> you figure out what kind of expansion you need and why.
>

Hi Todd,

I am learning shell scripting as suggested by you after going through
oreilly books(Learning the Bash Shell).
I could not proceed from there.

Please guide.

Thanks,

Kaushal
Todd A. Jacobs | 3 Dec 20:43 2009

Re: Parameter Expansion

On Thu, Dec 03, 2009 at 10:36:27PM +0530, Kaushal Shriyan wrote:

> I could not proceed from there.

The bash manual is a little terse, but fairly thorough:

    http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion

on the subject of parameter expansion. Think of parameter expansions as
transformations of the values of a variable, and it might make more
sense. In the manual, "parameter" means a variable name, while "word"
means the value to substitute for whatever is currently held in the
variable.

So, "echo ${foo:-bar}" will either print the value of $foo, or print
"bar" if $foo is unset. This is the expansion I use most, as it's a
great way to set default values for things, and it has the side-effect
of giving you a value while still leaving $foo unset.

You don't really need them, though. They are convenience functions. You
could accomplish the same thing with:

    if [[ -n $foo ]]; then
	foo="bar"
    fi

or:

    test -n "$foo" || foo="bar"

(Continue reading)

Cameron Simpson | 4 Dec 03:07 2009
Picon
Picon

Re: Parameter Expansion

On 03Dec2009 11:43, Todd A. Jacobs <nospam@...> wrote:
| On Thu, Dec 03, 2009 at 10:36:27PM +0530, Kaushal Shriyan wrote:
| > I could not proceed from there.
| 
| The bash manual is a little terse, but fairly thorough:
| 
|     http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion
| 
| on the subject of parameter expansion. Think of parameter expansions as
| transformations of the values of a variable, and it might make more
| sense. In the manual, "parameter" means a variable name, while "word"
| means the value to substitute for whatever is currently held in the
| variable.
| 
| So, "echo ${foo:-bar}" will either print the value of $foo, or print
| "bar" if $foo is unset. This is the expansion I use most, as it's a
| great way to set default values for things, and it has the side-effect
| of giving you a value while still leaving $foo unset.
| 
| You don't really need them, though. They are convenience functions. You
| could accomplish the same thing with:
| 
|     if [[ -n $foo ]]; then
| 	foo="bar"
|     fi
| 
| or:
| 
|     test -n "$foo" || foo="bar"
| 
(Continue reading)

Todd A. Jacobs | 4 Dec 07:04 2009

Re: Parameter Expansion

On Fri, Dec 04, 2009 at 01:07:47PM +1100, Cameron Simpson wrote:

> Well, technically these last two are a little different in that they
> change $foo.

You're absolutely right. To be fair, I mentioned that ":-" substituted
without assignment, but in retrospect the way I said it probably wasn't
any clearer than the manual itself. Thanks for clarifying!

> And once you have the ${foo} syntax, you then have some syntactic
> scope you didn't have before, because you have room to put in all
> sorts of stuff after "${foo" before the closing "}". And that's when
> you get all these handy syntaxes like ${foo:-bar} and so on to get
> various results.

This is a great explanation.

Of course, you can do some really non-intuitive things with these
constructs, too:

    $ foo=bar
    $ fubar=baz
    $ echo ${foo:+$fubar}
    baz

Generally, I think clarity should be more important than saving a few
lines of code. Somehow, though, I just couldn't bring myself to do this:

    foo=bar
    fubar=baz
(Continue reading)

Kaushal Shriyan | 4 Dec 07:48 2009
Picon

Re: Parameter Expansion

On Fri, Dec 4, 2009 at 11:34 AM, Todd A. Jacobs <nospam@...> wrote:
> On Fri, Dec 04, 2009 at 01:07:47PM +1100, Cameron Simpson wrote:
>
>> Well, technically these last two are a little different in that they
>> change $foo.
>
> You're absolutely right. To be fair, I mentioned that ":-" substituted
> without assignment, but in retrospect the way I said it probably wasn't
> any clearer than the manual itself. Thanks for clarifying!
>
>> And once you have the ${foo} syntax, you then have some syntactic
>> scope you didn't have before, because you have room to put in all
>> sorts of stuff after "${foo" before the closing "}". And that's when
>> you get all these handy syntaxes like ${foo:-bar} and so on to get
>> various results.
>
> This is a great explanation.
>
> Of course, you can do some really non-intuitive things with these
> constructs, too:
>
>    $ foo=bar
>    $ fubar=baz
>    $ echo ${foo:+$fubar}
>    baz
>
> Generally, I think clarity should be more important than saving a few
> lines of code. Somehow, though, I just couldn't bring myself to do this:
>
>    foo=bar
(Continue reading)

Roger | 4 Dec 23:54 2009
Picon

Re: Parameter Expansion

On Thu, Dec 3, 2009 at 11:43 AM, Todd A. Jacobs <nospam@...> wrote:
> So, "echo ${foo:-bar}" will either print the value of $foo, or print
> "bar" if $foo is unset. This is the expansion I use most, as it's a
> great way to set default values for things, and it has the side-effect
> of giving you a value while still leaving $foo unset.

real world example could be a script that could take up to 3 variable,
then have the code:
FIRST=${1:-'default first value'}
SECOND=${2:-"default second value"}
THIRD=${3:-"default third value"}

If the person leaves off any of the command line parameters, they'd be
set with those 3 lines, right?

Roger
Cameron Simpson | 5 Dec 10:10 2009
Picon
Picon

Re: Parameter Expansion

On 04Dec2009 14:54, Roger <roger.in.eugene@...> wrote:
| On Thu, Dec 3, 2009 at 11:43 AM, Todd A. Jacobs <nospam@...> wrote:
| > So, "echo ${foo:-bar}" will either print the value of $foo, or print
| > "bar" if $foo is unset. This is the expansion I use most, as it's a
| > great way to set default values for things, and it has the side-effect
| > of giving you a value while still leaving $foo unset.
| 
| real world example could be a script that could take up to 3 variable,
| then have the code:
| FIRST=${1:-'default first value'}
| SECOND=${2:-"default second value"}
| THIRD=${3:-"default third value"}
| 
| If the person leaves off any of the command line parameters, they'd be
| set with those 3 lines, right?

Yes, but I like to pay closer attention to the command line; in
particular if anything's wrong it's best to complain and abort in case
they've mis-invoked this script, intending another command. So I try to
be really picky - it pays off.

So I'd be writing:

  # top of script, under opening comment - doubles as documentation
  usage="Usage: $0 [first [second [third]]]

  # sometimes ahead of usage, in case you want to display defaults in
  # the usage message; often helpful
  first='default first value'
  second='default second value'
(Continue reading)

Ken Irving | 10 Dec 23:41 2009
Picon

environment variables in all-caps

On Sat, Dec 05, 2009 at 08:10:57PM +1100, Cameron Simpson wrote:
> it is common to allow environment variables to control the default
> behaviour of various commands, such as $EDITOR to specify the user's
> preferred editor. So I often have:
> 
>   : ${MYCMD_THIS:='default first value'}
>   : ${MYCMD_THAT:='default second value'}
>   : ${MYCMD_TOTHER:='default third value'}
> 
> if it is reasonable. Note that because these are now _public_ environment
> variables, they are in capitals. Script local variables should have
> lowercase names to avoid conflicts with public names. I can go into this
> in more detail if someone asks - the requirement is quite real.

I'm interested in this, and have gone back & forth on capitalizing exported
variables.  When you say "_public_ environment variables", are you implying
that there are non-public ones that would not be in all caps?

I've used a convention of capitalizing the common prefix, but not the
rest, e.g. from the above example, MYCMD_this, MYCMD_that, MYCMD_tother.
Should these instead be in all caps? 

Thanks,

Ken

--

-- 
Ken.Irving@...
Cameron Simpson | 11 Dec 01:19 2009
Picon
Picon

Re: environment variables in all-caps

On 10Dec2009 13:41, Ken Irving <k.irving@...> wrote:
| On Sat, Dec 05, 2009 at 08:10:57PM +1100, Cameron Simpson wrote:
| > it is common to allow environment variables to control the default
| > behaviour of various commands, such as $EDITOR to specify the user's
| > preferred editor. So I often have:
| > 
| >   : ${MYCMD_THIS:='default first value'}
| >   : ${MYCMD_THAT:='default second value'}
| >   : ${MYCMD_TOTHER:='default third value'}
| > 
| > if it is reasonable. Note that because these are now _public_ environment
| > variables, they are in capitals. Script local variables should have
| > lowercase names to avoid conflicts with public names. I can go into this
| > in more detail if someone asks - the requirement is quite real.
| 
| I'm interested in this, and have gone back & forth on capitalizing exported
| variables.  When you say "_public_ environment variables", are you implying
| that there are non-public ones that would not be in all caps?

I take we accept as a given that things like $HOME, $EDITOR, $LOCALE,
$PATH are all "public" environment variables. This means well known
names, _exported_ to all processes.

Second, neither you no I will know all such variables, as various
packages may use anything. But they've still got upper case names [1].

A process inherits exported variables from its parent when it starts,
and they are automatically exports to the program's children.

Now consider a shell script that goes:
(Continue reading)

Ken Irving | 11 Dec 02:00 2009
Picon

Re: environment variables in all-caps

On Fri, Dec 11, 2009 at 11:19:42AM +1100, Cameron Simpson wrote:
> On 10Dec2009 13:41, Ken Irving <k.irving@...> wrote:
> We know to stay away from the common names (EDITOR, PATH etc).
> But since we can't know "all" such names, the only way to be safe is to
> use non-uppercase names for non-exported variables, and rely on others
> to do the same.
>
> Hence the convention.
>
> Provided scripts use lowercase names for "private"/"unexported" variables
> everyone gets along.
>
> | I've used a convention of capitalizing the common prefix, but not the
> | rest, e.g. from the above example, MYCMD_this, MYCMD_that, MYCMD_tother.
> | Should these instead be in all caps?
>
> It may not matter. You're talking about exported names, yes?
> Provided they start with an upper case letter people using the
> convention will be ok.

I agree with all of that.  The prefix is more or less laying claim to
a namespace in the environment being passed along to child processes.

Thanks,

Ken

--
Ken.Irving@...
(Continue reading)

Todd A. Jacobs | 13 Dec 01:24 2009

Re: environment variables in all-caps

On Thu, Dec 10, 2009 at 04:00:25PM -0900, Ken Irving wrote:

> I agree with all of that.  The prefix is more or less laying claim to
> a namespace in the environment being passed along to child processes.

A lot of people will also code defensively by putting x or _ before a
variable, like:

    if [ x"${SOMEVAR}" = x"foo" ]; then
	_SOMEOTHERVAR=bar
    fi

as a way to try and minimize namespace collisions, so what you're doing
is really no different. As for myself, I try to use all-caps inside
scripts for things I want to treat as constants, but I rarely use the
readonly built-in to enforce it.

Generally, the only safe choice is to ensure you validate (or assign)
all variables before using or over-writing them, which is why constructs
like ${EDITOR:=/usr/bin/vim} are so important.

When you get right down to it, a script really shouldn't assume that
*any* variable set outside itself is valid. After all, even if EDITOR is
set, you'd want to be really sure it isn't EDITOR=/bin/rm before you run
"$EDITOR /etc/passwd" or similar as root.

Realistically, that sort of advice gets ignored about as often as the
DMV's recommendation that people do a full inspection of their car each
time they plan to get on the road. I know *I* don't check my tire
pressure every morning, nor do I always validate every environment
(Continue reading)


Gmane