POSIX-Compliant Way to Scope Variables to a Function in a Shell Script -


is there posix compliant way limit scope of variable function declared in? i.e.:

testing() {     test="testing" }  testing echo "test is: $test" 

should print "test is:". i've read declare, local, , typeset keywords, doesn't required posix built-ins.

it done local keyword, is, seem know, not defined posix. here informative discussion adding 'local' posix.

however, primitive posix-compliant shell know of used gnu/linux distributions /bin/sh default, dash (debian almquist shell), supports it. freebsd , netbsd use ash, original almquist shell, supports it. openbsd uses ksh implementation /bin/sh supports it. unless you're aiming support non-gnu non-bsd systems solaris, or using standard ksh, etc., away using local. (might want put comment right @ start of script, below shebang line, noting not strictly posix sh script. not evil.) having said that, might want check respective man-pages of these sh implementations support local, since might have subtle differences in how work. or don't use local:

if want conform posix, or don't want mess possible issues, , not use local, have couple options. answer given lars brinkhoff sound, can wrap function in sub-shell. might have other undesired effects though. way shell grammar (per posix) allows following:

my_function() (   # in sub-shell here,   # i'm using ( , ) function's body , not { , }. ) 

although maybe avoid super-portable, old bourne shells can non-posix-compliant. wanted mention posix allows it.

another option unset variables @ end of function bodies, that's not going restore old value of course isn't want guess, merely prevent variable's in-function value leak outside. not useful guess.

one last, , crazy, idea can think of implement local yourself. shell has eval, which, evil, yields way insane possibilities. following implements dynamic scoping la old lisps, i'll use keyword let instead of local further cool-points, although have use so-called unlet @ end:

# if want can add error-checking , what-not this.  @ present, # wrong usage (e.g. passing string whitespace in `let', not # balancing `let' , `unlet' calls variable, etc.) yield # very confusing error messages or breakage.  it's dirty code, # wrote down pretty @ 1 go.  clean up.  let() {     dynvar_name=$1;     dynvar_value=$2;      dynvar_count_var=${dynvar_name}_dynvar_count     if [ "$(eval echo $dynvar_count_var)" ]             eval $dynvar_count_var='$(( $'$dynvar_count_var' + 1 ))'     else         eval $dynvar_count_var=0     fi      eval dynvar_oldval_var=${dynvar_name}_oldval_'$'$dynvar_count_var     eval $dynvar_oldval_var='$'$dynvar_name      eval $dynvar_name='$'dynvar_value }  unlet() dynvar_name     dynvar_count_var=${dynvar_name}_dynvar_count     eval dynvar_oldval_var=${dynvar_name}_oldval_'$'$dynvar_count_var     eval $dynvar_name='$'$dynvar_oldval_var     eval unset $dynvar_oldval_var     eval $dynvar_count_var='$(( $'$dynvar_count_var' - 1 ))' done 

now can:

$ let foobar test_value_1 $ echo $foobar test_value_1 $ let foobar test_value_2 $ echo $foobar test_value_2 $ let foobar test_value_3 $ echo $foobar test_value_3 $ unlet foobar $ echo $foobar test_value_2 $ unlet foobar $ echo $foobar test_value_1 

(by way unlet can given number of variables @ once (as different arguments), convenience, not showcased above.)

don't try @ home, don't show children, don't show co-workers, don't show #bash @ freenode, don't show members of posix committee, don't show mr. bourne, maybe show father mccarthy's ghost give him laugh. have been warned, , didn't learn me.

edit:

apparently i've been beaten, sending irc bot greybot on freenode (belongs #bash) command "posixlocal" make give 1 obscure code demonstrates way achieve local variables in posix sh. here cleaned version, because original difficult decipher:

f() {     if [ "$_called_f" ]             x=test1         y=test2         echo $x $y     else         _called_f=x x= y= command eval '{ typeset +x x y; } 2>/dev/null; f "$@"'     fi } 

this transcript demonstrates usage:

$ x=a $ y=b $ f test1 test2 $ echo $x $y b 

so lets 1 use variables x , y locals in then branch of if form. more variables can added @ else branch; note 1 must add them twice, once variable= in initial list, , once passed argument typeset. note no unlet or needed (it's "transparent" implementation), , no name-mangling , excessive eval done. seems cleaner implementation overall.

edit 2:

comes out typeset not defined posix, , implementations of almquist shell (freebsd, netbsd, debian) don't support it. above hack not work on platforms.


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -