Hi there,
I'm writing a shellscript which consists of a function which gets called
somewhere in the main loop. In order to keep things as tidy as possible
I'm defining a local variable inside the function. I know how to do this
in Bash, I learned how to do this in Korn but /bin/sh is giving me some
difficulties.
I know that sh (I always keep forgetting its real name) is almost equal
to ksh except when mentioned otherwise in the documentation. However,
since nothing explicitly tells me any differences on functions or
variable definitions I'm wondering whats happening here.
After reading ksh(1) I discovered that I need the "typeset special
command" to define a variable within the function in order to make it
local, I quote: "However, the typeset special command used within a
function defines local variables whose scope includes the current
function and all functions it calls.".
At first I thought to be dealing with a command like "local" in Bash
(this keyword is solely used to define a local variable) however reading
typeset(1) taught me that its a little more versatile than that:
typeset(1):
SYNOPSIS
typeset [ + HLRZfilrtux [n]] [ name [ = value]]...
whence [-pv] name...
While my current script works excellent on the Korn shell, it doesn't do
what I want (define a local variable) on the sh shell. My guess is that
this is a sh limitation:
#/bin/ksh
GVAR="global"
varfunc() {
typeset LVAR
LVAR=$GVAR
echo "Local variable : $LVAR";
}
varfunc
echo "Global variable: $GVAR"
echo "Export variable: $LVAR"
exit
You'll notice that if you change the shebang into /bin/sh it will
produce an error about not being able to find 'typeset'. So after
commenting it out you'll notice that LVAR is made global. Right now I
can only conclude that I found a sh limitation because it doesn't
support the 'typeset' command as ksh does, but I can't help wonder if
I'm not overlooked something obvious here. Am I ?
Thanks in advance for any comments.
--
Groetjes, Peter
..\\ PGP/GPG key: http://www.catslair.org/pubkey.asc
|
|
0
|
|
|
|
Reply
|
Lion
|
9/28/2005 2:48:33 PM |
|
Lion-O wrote:
> Hi there,
>
> I'm writing a shellscript which consists of a function which gets called
> somewhere in the main loop. In order to keep things as tidy as possible
> I'm defining a local variable inside the function. I know how to do this
> in Bash, I learned how to do this in Korn but /bin/sh is giving me some
> difficulties.
>
> I know that sh (I always keep forgetting its real name) is almost equal
> to ksh except when mentioned otherwise in the documentation. However,
> since nothing explicitly tells me any differences on functions or
> variable definitions I'm wondering whats happening here.
>
> After reading ksh(1) I discovered that I need the "typeset special
> command" to define a variable within the function in order to make it
> local, I quote: "However, the typeset special command used within a
> function defines local variables whose scope includes the current
> function and all functions it calls.".
>
> At first I thought to be dealing with a command like "local" in Bash
> (this keyword is solely used to define a local variable) however reading
> typeset(1) taught me that its a little more versatile than that:
>
> typeset(1):
>
> SYNOPSIS
> typeset [ + HLRZfilrtux [n]] [ name [ = value]]...
>
> whence [-pv] name...
>
>
> While my current script works excellent on the Korn shell, it doesn't do
> what I want (define a local variable) on the sh shell. My guess is that
> this is a sh limitation:
>
> #/bin/ksh
>
> GVAR="global"
>
> varfunc() {
> typeset LVAR
> LVAR=$GVAR
> echo "Local variable : $LVAR";
> }
>
> varfunc
> echo "Global variable: $GVAR"
> echo "Export variable: $LVAR"
> exit
>
>
> You'll notice that if you change the shebang into /bin/sh it will
> produce an error about not being able to find 'typeset'. So after
> commenting it out you'll notice that LVAR is made global.
No... LVAR will be local to the current process. In shell a global
variable would be one that can be seen by the process children (sub
processes).
So.. depending on your function.. .you may be able to get away
with executing your shell function in a sub process shell.
e.g.
myfunc() {
mylocal=1
myglobal=B
echo "myfunc mylocal=$mylocal"
echo "myfunc myglobal=$myglobal"
}
myglobal=A
export myglobal
mylocal=2
echo "main mylocal=$mylocal"
echo "main myglobal=$myglobal"
(myfunc)
echo "main mylocal=$mylocal"
echo "main myglobal=$myglobal"
Of course, if myfunc needs to manipulate a global (environment)
variable, this isn't going to work.. the sub process can use
the variable, but any mods will not magically make it back to
the parent.
You could return a string from your function that contains
variable assignments and eval them in the parent. But eval might
be a bit tricky depending on the data.
> Right now I
> can only conclude that I found a sh limitation because it doesn't
> support the 'typeset' command as ksh does, but I can't help wonder if
> I'm not overlooked something obvious here. Am I ?
>
> Thanks in advance for any comments.
>
|
|
0
|
|
|
|
Reply
|
Chris
|
9/28/2005 6:33:58 PM
|
|
Lion-O wrote:
> Hi there,
>
> I'm writing a shellscript which consists of a function which gets called
> somewhere in the main loop. In order to keep things as tidy as possible
> I'm defining a local variable inside the function. I know how to do this
> in Bash, I learned how to do this in Korn but /bin/sh is giving me some
> difficulties.
To my knowledge, Bourne shell does not support local variables.
All variables within a shell (ignoring things like subshells)
have the same scope.
You can fix this to some extent by using funny names:
myfunc ()
{
myfunc_var1="$1"
myfunc_var2=`echo "$myfunc_var1" | sed -e s/foo/bar/`
}
That at least prevents name collisions, but it doesn't make a separate
instance of the variable for each function invocation, so it leaves
you with something like a static variable in C. As Chris said, you
can use a subshell in some cases:
myfunc ()
{
(
# function body goes here
)
}
I'm not sure whether the parameters like $1 go through to the subshell,
though.
- Logan
|
|
0
|
|
|
|
Reply
|
Logan
|
9/28/2005 7:26:05 PM
|
|
>> I'm defining a local variable inside the function. I know how to do
>> this in Bash, I learned how to do this in Korn but /bin/sh is giving
>> me some difficulties.
> To my knowledge, Bourne shell does not support local variables.
Thanks. This seems to be confirmed by other people as well so I guess I
drew the right conclusions. Fortunatly it really isn't very important,
just something which really kept me wondering. So global variables it
is.
And next time I'll really try harder to remember 'Bourne'. I even know
about Bash (Bourne Again SHell) yet totally forget about the original.
Oh well ;)
> You can fix this to some extent by using funny names:
*nod*. I know a few options to do that, even re-defining is a valid
option here. But my underlying motivation to make it local was merely
from a memory and "tidyness" point of view.
Thanks for the examples.
--
Groetjes, Peter
..\\ PGP/GPG key: http://www.catslair.org/pubkey.asc
|
|
0
|
|
|
|
Reply
|
Lion
|
9/29/2005 6:24:46 PM
|
|
Logan Shaw <lshaw-usenet@austin.rr.com> wrote:
> Lion-O wrote:
>> Hi there,
>>
>> I'm writing a shellscript which consists of a function which gets called
>> somewhere in the main loop. In order to keep things as tidy as possible
>> I'm defining a local variable inside the function. I know how to do this
>> in Bash, I learned how to do this in Korn but /bin/sh is giving me some
>> difficulties.
>
> To my knowledge, Bourne shell does not support local variables.
> All variables within a shell (ignoring things like subshells)
> have the same scope.
>
> You can fix this to some extent by using funny names:
For /bin/sh-scripts I use leading underscores in the variable names.
Usually one leading underscore per nesting level the function will be
likely called:
l2()
{
__var="xxx"
}
l1()
{
_var="xxx"
l2
}
# "main" function
var="xxx"
l1
The only problem would be functions which could be called from different
levels, but for these you choose your variable names carefully.
But I rarely write pure /bin/sh scripts any more. You either have a ksh or
the /bin/sh on other systems isn't as primitive as on Solaris.
--
Daniel
|
|
0
|
|
|
|
Reply
|
Daniel
|
9/29/2005 7:24:50 PM
|
|
Lion-O wrote:
> I know that sh [...] is almost equal to ksh except when mentioned
> otherwise in the documentation.
You can add <http://www.in-ulm.de/~mascheck/bourne/common.html>,
(typical differences of traditional Bourne shells to bourne compatibles)
--
|
|
0
|
|
|
|
Reply
|
Sven
|
10/15/2005 10:43:23 PM
|
|
|
5 Replies
735 Views
(page loaded in 0.109 seconds)
|