I want to create a simple dialog with bash-dialog. I work with (X)DSL and bash-3.2. The latest (X)DSL is based on Linux 2.4.31 and comes with bash-2.05, however, bash-3.2 is downloadable from MyDSL/Testing. So, my script runs under '#!/bin/bash-3.2/bin/bash'.
The menu items the users can choose from come from a database.
Example database file 'armatures':
Indoor Lighting|Lighting for Indoor use
Outdoor Lighting|Lighting for Outdoor use
I retrieve the data into an array 'options' from the 'armatures' file with:
options=($(awk -F"|" '{ print $1,$2 }' armatures)
and in terminal 'echo' the array:
echo ${options[@]}
which shows:
"Indoor Armatures" "Lighting for Indoor use" "Outdoor Armatures" "Lighting for Outdoor use"
This looks OK to use as a selection menu with 'whiptail' but it isn't. The command line:
whiptail --clear --title "Armatures" --menu "Choose an armature" 50 80 10 ${options[@]}
shows:
column1-column2
Indoor-Armatures
Lighting-for
Indoor-use
Outdoor-Armatures
Lighting-for
Outdoor-use
in stead of:
column1-column2
Indoor armatures-Lighting for Indoor use
Outdoor armatures-Ligthing for Outdoor use
It seems that array elements with double quotes are ignored or not seen by 'whiptail'. I also tried "${options[@]}" but that always results on the first word 'Indoor'.
Aside from 'whiptail' I tried 'dialog' but they are the same: version information shows 'cdialog (ComeOn Dialog!) version 1.1-20080316' in both cases.
I have very limited resources and don't want to venture (yet) into 'xdialog', 'zenity', 'dzen' and the like, even if that would solve this. I am also limited to Linux 2.4.31 due to XDSL (for XBOX).
I've been browsing the Internet a lot but to no avail. What could be the solution with 'whiptail/dialog'?
The basic problem you are having comes from the order in which the shell parses command lines: it parses (and removes) quotes and escapes before it replaces variables with their values, and it never goes back and re-parses for any quotes or escapes within the replaced values. Consider this example:
var='"foo bar"' # Note that the single-quotes will be removed, and the
# double-quotes will be treated as part of the variable value.
somecmd $var # This runs cmd with 2 arguments: '"foo' and 'bar"'
In your case, I'm not sure where the double-quotes are coming from; they're not in the file listing you provided and the awk command won't add them. But in any case, you don't want them stored as part of the value, you want them around the variable reference:
var='foo bar' # Again, the single-quotes are removed.
somecmd "$var" # This runs cmd with a single argument: 'foo bar'
Your case is a little more complicated since you're using an array, but the same principle applies. Note that echo
ing a variable is highly misleading; if it shows what looks like proper quoting, that actually means there's something horribly wrong because it should show the arguments after quote removal.
So, how do you solve it? Try this:
options=()
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
options+=("$col1" "$col2") # Note the double-quotes around the variable references
done <armatures
echo "options:"
printf " '$s'\n" "${options[@]}" # This prints each array element on a separate line
whiptail --clear --title "Armatures" --menu "Choose an armature" 50 80 10 "${options[@]}" # Again, double-quotes around the reference
UPDATE: I added a test ([ -n "$col1" ]
) to execute the loop for an unterminated last line in the database file.
If the double-quotes are actually in the database file, you'll have to remove them; the easiest way to handle this probably to strip quotes while adding the strings to the array, using bash's ability to so string replacement (replacing '"' with blank) while building the array:
options=()
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
options+=("${col1//'"'/}" "${col2//'"'/}")
done <armatures