Updated October 23, 2004
Created October 12, 2004
Autogenerated Site Map
Search this Site!:
This builds on the "Variable Indirection" found later on this page.
I actually got a trailing "_VALIDATION" to stick to several individual indirect variables:
64 validate_variables()
65 {
66 for VARIABLE_ITEM in $VARIABLE_LIST; do
# Snips off a default value which starts at =.*$
67 VARIABLE_ITEM=`echo $VARIABLE_ITEM | sed -e 's/=.*$//'`
68 if [ -n "${!VARIABLE_ITEM}" ]; then
# I am pulling preconfigured grep entries from a flat file which contains ^, $, and \| (beginning, end, or).
69 GREPCMD=`cat field-validation.txt | grep ^$VARIABLE_ITEM | head -1 | sed -e "s/^$VARIABLE_ITEM *\t*//"`
# validate variable with its given grep command
70 echo ${!VARIABLE_ITEM} | grep $GREPCMD >/dev/null 2>&1 && {
71 # Validation passed
72 export ${VARIABLE_ITEM}_VALIDATION=1
73 } || {
74 # Validation failed
75 export ${VARIABLE_ITEM}_VALIDATION=0
76 echo sorry item $VARIABLE_ITEM did not pass validation
77 }
78 set | grep -i VALIDATION
79 exit
80 fi
81 done
82 }
Output:
SERIALNUMBER_VALIDATION=0
... other snipped garbage ...
So this means I can build all kinds of indirect variables where I identify items such as their default value and stick it into VariableName_DEFAULT, etc. It is almost like an array where the actual variable name is the handle (index/key, whatever the call it).
I will use this "validation result" later on when displaying the page to determine if I need to flag it for user attention.
Ok, trying to use it with just plain Bash parameter expansion. I haven't figured that one out just yet. Any ideas? Well, here is what I am using in the mean time - I know there has to be a way to bend bash to do a 2nd pass scan, just can't think of it:
96 if [ "`set | grep ^${VARIABLE_ITEM}_VALIDATION= | sed -e 's/^.*=//'`" = "1" ]; then
97 echo -n '<font color="red">'
98 fi
101 if [ "`set | grep ^${VARIABLE_ITEM}_VALIDATION= | sed -e 's/^.*=//'`" = "1" ]; then
102 echo -n '</font>'
103 fi
Bash debugging
This turns on debugging for your entire script:
#!/bin/bash -x
Or in your body of code you need to debug:
... normal code ...
set -o xtrace
# tracing is now turned on...
... buggy code to debug ...
set +o xtrace
# trace is now turned off...
... normal code ...
When debugging bash (-x or xtrace), the number of leading plus signs shows if you are in a subshell or not. It shows you the level of subshells deep the commands are operating. Example, here is a single run of a for loop snippet. Notice how the double plus signs (++) correspond with the backticks (backticks open up a subshell):
++ echo UNITNUM
++ sed -e 's/=.*$//'
+ VARIABLE_ITEM=UNITNUM
+ echo -n '<tr><td>'
++ set
++ sed -e 's/^.*=//'
++ grep '^UNITNUM_VALIDATION='
+ '[' -1 = 1 ']'
+ grep UNITNUM
+ head -1
+ read ONE TWO
+ cat field-wording.txt
+ echo -n Unit Number:
+ read ONE TWO
++ set
++ grep '^UNITNUM_VALIDATION='
++ sed -e 's/^.*=//'
+ '[' -1 = 1 ']'
+ echo -n '</td><td>'
+ echo -n '<input type=text name="'
+ echo -n UNITNUM
+ tr '[:upper:]' '[:lower:]'
+ echo -n '" value="'
+ echo -n ''
+ echo -n '">'
+ echo '</td></tr>'
|
280 for VARIABLE_ITEM in $VARIABLE_LIST; do
281 VARIABLE_ITEM=`echo $VARIABLE_ITEM | sed -e 's/=.*$//'`
282 echo -n "<tr><td>"
283 if [ "`set | grep ^${VARIABLE_ITEM}_VALIDATION=
| sed -e 's/^.*=//'`" = "1" ]; then
284 echo -n '<font color="red">'
285 fi
286 cat field-wording.txt | grep $VARIABLE_ITEM | head -1
| while read ONE TWO; do echo -n $TWO; done
287 if [ "`set | grep ^${VARIABLE_ITEM}_VALIDATION=
| sed -e 's/^.*=//'`" = "1" ]; then
288 echo -n '</font>'
289 fi
290 echo -n "</td><td>"
291 echo -n "<input type=text name=\""
292 echo -n $VARIABLE_ITEM | tr [:upper:] [:lower:]
293 echo -n "\" value=\""
294 echo -n "${!VARIABLE_ITEM}"
295 echo -n "\">"
296 echo "</td></tr>"
297 done
|
I word wrapped 3 of the above lines (283, 286, and 287)
VAR=VALUE
export VAR=VALUE
Variable Scope - Ok items: for, while, if, &&, ||, {}, functions
for X in 1; do VARPLAIN=forloop; export VAREXPORT=forloop; done; echo $VARPLAIN; echo $VAREXPORT
while :; do VARPLAIN=aaa; export VAREXPORT=abc; break; done; echo $VARPLAIN; echo $VAREXPORT
{ while :; do VARPLAIN=111; export VAREXPORT=222; break; done; }; echo $VARPLAIN; echo $VAREXPORT
if [ 1 -eq 1 ]; then { while :; do VARPLAIN=777; export VAREXPORT=888; break; done; }; fi; echo $VARPLAIN; echo $VAREXPORT
echo hi | grep hi >/dev/null && { VARPLAIN=22222; export VAREXPORT=44444; }; echo $VARPLAIN; echo $VAREXPORT
echo $HI; myfunc(){ HI=3;}; myfunc; echo $HI
Variable Scope is lost when a subshell is used: (), |, ``
Parenthesis, pipes, and backticks open up subshells:
( while :; do VARPLAIN=333; export VAREXPORT=444; break; done; ); echo $VARPLAIN; echo $VAREXPORT
( VARPLAIN=999; export VAREXPORT=101; ); echo $VARPLAIN; echo $VAREXPORT
echo hellothere | while read; do VARPLAIN=555; export VAREXPORT=678; break; done; echo $VARPLAIN; echo $VAREXPORT
echo $HI; echo `echo setting HI in backticks; HI=hello; echo Value inside backticks $HI`; echo Value outside: $HI
Bash Variable Indirection - Setting and accessing variables indirectly
# List of variables I want to create and manipulate:
VARIABLE_LIST="
SERIALNUMBER
ASSETTAG
MACADDR1
MACADDR2
RACKNUM
UNITNUM
IPADDRESS
"
# Simple for loop to set each variable to "hello":
for VARIABLE_ITEM in $VARIABLE_LIST; do
echo Working on $VARIABLE_ITEM
export ${VARIABLE_ITEM}=hello
echo Item is: ${VARIABLE_ITEM}
echo Item Value is: ${!VARIABLE_ITEM}
done
# Proof that these variables are now in the environment:
set
# Ok, the above explains well, but does not show why you would want such a thing.
# I have a list of variables I want treated equally. They will drive the creation
# of various web pages. I don't want to create many needless lines of duplicate
# code - all doing the same thing, just with different variables -- not to mention
# if I goof a line.
# Here is one of the original for loops manipulating them as part of a cgi script in progress:
for VARIABLE_ITEM in $VARIABLE_LIST; do
VARIABLE_ITEM_LOWER=`echo $VARIABLE_ITEM | tr [:upper:] [:lower:]`
echo $VARIABLE_ITEM
echo $VARIABLE_ITEM_LOWER
# Set the individual variable
export ${VARIABLE_ITEM}=`echo $MYVAR | tr '&' '\n' | grep $VARIABLE_ITEM_LOWER | sed -e "s/$VARIABLE_ITEM_LOWER=//g"`
# Display which variable I set
echo Item is ${VARIABLE_ITEM}
# Display the value of the variable I set
echo Item Value is ${!VARIABLE_ITEM}
done
# Proof that the variable is indeed set and has a particular value...
set
# For a better understanding of what I am pulling out of $MYVAR, look inside http://www.cpqlinux.com/cal.cgi
Bash supports more than 0 - 9 positional parameters. Access them via:
$0, $1, ... $9, ${10}, ..., ${15}, ...
Handling filenames with spaces:
This cp command won't handle spaces in the filenames:
for X in `find . -type f -name '*html'`; do cp -al "$X" /tmp/html/; done
This cp command will handle filenames with spaces:
find . -type f -name '*html' | while read; do cp -al "$REPLY" /tmp/html/; done
Search this Site!:
Homepage: http://www.cpqlinux.com
Site Map: http://www.cpqlinux.com/sitemap.html