![]() |
|
|||||||
| Programming C, bash, Python, Perl, PHP, Java, you name it. |
![]() |
|
|
Thread Tools | Display Modes |
|
|
|
|||
|
In a Linux Journal Tech tip is shown how you can dereference a variable, when it is passed as string to a function. It uses the bash ! operator.
Code:
DerefernceVariablePassedToFunction() {
if [ -n "$1" ] ; then
echo "value of [${1}] is: [${!1}]"
else
echo "Null parameter passed to this function"
fi
}
Variable="LinuxJournal"
DerefernceVariablePassedToFunction Variable
I just wondered why he did not use eval like this Code:
#/bin/sh
dereference() {
if [ -n "$1" ] ; then
eval echo value of \$1 is: \$$1
else
echo "Null parameter passed to this function"
fi
}
variable="Just use 'eval'"
dereference variable
Code:
sh -vx dereference.sh
#/bin/sh
dereference() {
if [ -n "$1" ] ; then
eval echo value of \$1 is: \$$1
else
echo "Null parameter passed to this function"
fi
}
variable="Just use 'eval'"
+ variable=Just use 'eval'
dereference variable
+ dereference variable
echo value of $1 is: $variable
value of variable is: Just use 'eval'
echo value of \$1 is: \$$1into echo value of $1 is: $variable\$1 is seen by the shell as a "$" followed by a '1' . The "\" prevents the shell from interpreting $1 as the first parameter, as it normally would do. \$$1is parsed as a literal "$" followed by the function parameter $1 which contains the string "variable" The second and last pass re-processes this echo value of $1 is: $variableand without any "\" to prevent variable expansion, produces the wanted result: value of variable is: Just use 'eval'
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump |
|
||||
|
It's linux journal, people assume, who ever said they considered real portability
__________________
My Journal Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''. |
|
|||
|
Another demonstration of eval , but where we encounter something strange.
Code:
#!/bin/sh
fr_1=un
fr_2=deux
fr_3=trois
nl_1=een
nl_2=twee
nl_3=drie
de_1=eins
de_2=zwei
de_3=drei
one2three() {
local LANG
LANG="$1"
printf "\nCounting in : ${LANG}\n"
for nr in 1 2 3 ; do
eval printf "-%s" "\$$LANG_$nr"
done
printf "\n"
}
#typeset -ft one2three # trace into function (for ksh)
one2three nl
one2three fr
one2three de
Code:
$ ./lang-eval Counting in : nl -nl-- Counting in : fr -fr-- Counting in : de -de-- ![]() A run with a verbose shell trace shows : Code:
sh -vx lang-eval
#!/bin/sh
fr_1=un
+ fr_1=un
fr_2=deux
+ fr_2=deux
fr_3=trois
+ fr_3=trois
nl_1=een
+ nl_1=een
nl_2=twee
+ nl_2=twee
nl_3=drie
+ nl_3=drie
de_1=eins
+ de_1=eins
de_2=zwei
+ de_2=zwei
de_3=drei
+ de_3=drei
one2three() {
local LANG
LANG="$1"
printf "\nCounting in : ${LANG}\n"
for nr in 1 2 3 ; do
eval printf "-%s" "\$$LANG_$nr"
done
printf "\n"
}
#typeset -ft one2three # trace into function (for ksh)
one2three nl
+ one2three nl
Counting in : nl
printf -%s $1
-nlprintf -%s $2
-printf -%s $3
-
one2three fr
+ one2three fr
Counting in : fr
printf -%s $1
-frprintf -%s $2
-printf -%s $3
-
one2three de
+ one2three de
Counting in : de
printf -%s $1
-deprintf -%s $2
-printf -%s $3
-
Did you ever wonder why shell variables like "$name" are sometimes written as "${name}"? Well the above phenomenom is the reason. The underscore, "_", character is one of the valid characters in a variable name. So the shell seems to interpret "$LANG_", as a variable, which not defined anywhere in the script. We only define "$LANG" as local variable in the shell function, not "$LANG_". The solution is to use the curly braces to explicitly tell the shell where the variable name starts and ends. Code:
eval printf "-%s" "\$${LANG}_$nr"
Code:
Counting in : nl -een-twee-drie Counting in : fr -un-deux-trois Counting in : de -eins-zwei-drei Because a "-vx" verbose tracing does not work inside a function we first have to change Code:
#typeset -ft one2three # trace into function (for ksh) Code:
typeset -ft one2three # trace into function (for ksh) Code:
./lang-eval + typeset LANG + LANG=nl + printf \nCounting in : nl\n Counting in : nl + eval printf -%s $nl_1 + printf -%s een -een+ eval printf -%s $nl_2 + printf -%s twee -twee+ eval printf -%s $nl_3 + printf -%s drie -drie+ printf \n + typeset LANG + LANG=fr + printf \nCounting in : fr\n Counting in : fr + eval printf -%s $fr_1 + printf -%s un -un+ eval printf -%s $fr_2 + printf -%s deux -deux+ eval printf -%s $fr_3 + printf -%s trois -trois+ printf \n + typeset LANG + LANG=de + printf \nCounting in : de\n Counting in : de + eval printf -%s $de_1 + printf -%s eins -eins+ eval printf -%s $de_2 + printf -%s zwei -zwei+ eval printf -%s $de_3 + printf -%s drei -drei+ printf \n By using the curly braces "{}" , the shell does not have to guess anymore, which characters exactly make up the variable name end. In most cases it will guess correctly, but in this case it really needs a little help from it's curly friends
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump |
|
||||
|
I've found it a good habit, to reach for ${} whenever there will be characters intermixed with the variable names, in my scripts, this usually manifests itself as "${ham}/${spam}-${eggs}" and such.
I figure, it beats debugging silly errors if things ever get changed into a situation that needs expicit, or worrying about the possibility of some unexpected variable slipping into the execution environment later, and changing the implied behaviour. Sometimes code that is explicit is better documentation then a comment.
__________________
My Journal Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''. |
![]() |
| Tags |
| bash ! operator, curly braces, dereference, eval, variable name |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| passing make args/variables to builds of prerequisite ports | jbhappy | FreeBSD Ports and Packages | 2 | 18th July 2008 02:35 PM |