in section arrays, says that Bash provides one-dimensional indexed and associative array variables. Should work from bash 4.0 onward.
ksh should have associative arrays and can use the same logic. What would be the alternative to the true/false scheme I used. For single variables, the true/false should work. Or am I wrong in the conclusion. I tried it and did not encounter a problem.
---------- Post updated at 11:18 AM ---------- Previous update was at 10:37 AM ----------
How about trying what I suggested? Did it work, or did it not?
BASH is not C. I don't see any point in doing this. It's not going to make your code simpler. All you're going to do is make your code more and more complicated and strange.
Learn a tiny bit more about shell programming instead. Use variables as they're intended to be used. It looks unfamiliar to you because it's not familiar. Once you recognize it, it won't be.
What I would do is use bash's -z flag to tell if variables are empty. That way, you don't have to set a thousand different empty variables to zero -- just leave them blank. If they're still blank after processing options, then nobody set them.
case "$1" in
--something)
SOMETHING=1
;;
esac
if [ ! -z "$SOMETHING" ]
then
echo "Someone passed the --something option"
fi
I fully agree with you. I had ended up in the situation you describe, with the code getting too complicated. I was looking at removing the setting of lots of variables to zero.
Getting my code on this forum was a way to get input on the way forward. So thanks a lot for your contribution.
---------- Post updated at 12:38 PM ---------- Previous update was at 12:35 PM ----------
Yes, I tried perl and got things more complicated. So abandoned the perl strategy.
I think functions may be helpful to you in simplifying your code, and making it look better to you. In BASH and some KSH you can do this:
function isset # varname
{
[ -z "${!1}" ]
}
function notset # varname
{
[ ! -z "${!1}" ]
}
if isset VARIABLE # Note the lack of $
then
echo "VARIABLE is set, its value is $VARIABLE"
fi
if notset VARIABLE
then
echo "VARIABLE is not set"
fi
OLDIFS="$IFS"
IFS="|=" # IFS controls splitting. Split on "|" and "=", not whitespace.
set -- $* # Set the positional parameters to the command line arguments.
IFS="$OLDIFS"
declare -A hasArgument
while [ "$#" -gt 0 ]
do
case "$1" in
"--"[cC][mM][oO][dD]|\
"--"[cC][mM][oO][dD]"-"[iI][fF][lL])
shift
value_cmodIfl="$1"
hasArgument_cmodIfl=1
;;
"--"[sS][rR][cC][sS]|\
"--"[sS][rR][cC][sS]"-"[iI][fF][lL])
shift
value_srcsIfl="$1"
hasArgument_srcsIfl=1
;;
"--"[rR][cC][vV][sS]|\
"--"[rR][cC][vV][sS]"-"[iI][fF][lL])
shift
value_rcvsIfl="$1"
hasArgument_rcvsIfl=1
;;
*)
value_bdFileLst="$value_bdFileLst $1"
hasArgument_bdFileLst=1
hasArgument_bd=1
;;
esac
shift # Skip ahead to the next argument
done
if [ ! -z "$value_cmodIfl" ]
then
cmodIfl="$value_cmodIfl"
else
cmodIfl="$dflt_cmodIfl"
fi
I don't think you need any of them at all. You can tell if the variables are blank, why waste more variables storing things you can tell without them?
Also -- just set your defaults in the first place, and let the script change them later if they're given.
OLDIFS="$IFS"
IFS="|=" # IFS controls splitting. Split on "|" and "=", not whitespace.
set -- $* # Set the positional parameters to the command line arguments.
IFS="$OLDIFS"
# Just set the default in the first place.
value_cmodIfl="$dflt_cmodIfl"
while [ "$#" -gt 0 ]
do
case "$1" in
"--"[cC][mM][oO][dD]|\
"--"[cC][mM][oO][dD]"-"[iI][fF][lL])
shift
value_cmodIfl="$1"
;;
"--"[sS][rR][cC][sS]|\
"--"[sS][rR][cC][sS]"-"[iI][fF][lL])
shift
value_srcsIfl="$1"
;;
"--"[rR][cC][vV][sS]|\
"--"[rR][cC][vV][sS]"-"[iI][fF][lL])
shift
value_rcvsIfl="$1"
;;
*)
value_bdFileLst="$value_bdFileLst $1"
;;
esac
shift # Skip ahead to the next argument
done
if [ ! -z "$value_rcvsIfl" ]
then
echo "rcvsIfl given"
fi
I am getting a bit of problems with the following.
Output shows
agr1 set to
agr2 set to file.cmod
#!/bin/bash
function isSet
{
[ ! -z "$1" ]
}
function notSet
{
[ -z "$1" ]
}
agr2="file.cmod"
if isSet agr1; then
echo "agr1 set to $agr1"
fi
if notSet agr1; then
echo "agr1 not set"
fi
if isSet agr2; then
echo "agr2 set to $agr2"
fi
if notSet agr2; then
echo "agr2 not set"
fi
I agree with you. One problem is that some defaults require the use of mandatory values defined by the user, so I cannot put them all at the beginning. The result was that some defaults occurred in the beginning and some after the while loop. This used to be ok, but when amount of options got larger, it seems a good idea to group them all after the while loop.
---------- Post updated at 01:16 PM ---------- Previous update was at 01:08 PM ----------
Seems to work now with the following modifications
function isSet
{
[ ! -z "${!1}" ]
}
function notSet
{
[ -z "${!1}" ]
}
If you have lots and lots of optional, default, and mandatory values, you can do something like this:
# File listing variables and default values
# Mandatory value causes error if not set, printing errormessage from file
var1 mandatory errormessage
# Optional variable gets set to defaultvalue when absent
var2 optional defaultvalue
var3 optional defaultvalue
var4 optional defaultvalue
while read VAR TYPE STR
do
[ -z "$VAR" ] && continue # Skip blank lines
[ "${VAR:0:1}" = "#" ] && continue # Skip comments
case "$TYPE" in
mandatory)
if [ -z "${!VAR}" ] # Blank variable is an error
then
echo "$VAR not set: $STR"
exit
fi
;;
*) # If blank, set default
# <<< is a BASH-only syntax.
[ -z "${!VAR}" ] && read VAR <<<"$STR"
;;
esac
done < variablefile
I do not want the user to input the options interactively. The idea is that the user sets up a script with the sequence of operations he wants (run scripts and C++ programs), run the script, and no user requests are ever done. He then waits for the script to finish. In the meantime, he can check and do some analysis of the results as the sequence progresses.