I've got a BASH script that I'm wanting to have grab all SSIDs of nearby wireless networks and output them to a menu that users can choose from. I've got the portion to list out the networks, they get shown in a menu and the resulting SSID gets saved to a variable.
The issue, is when any of the networks have a space in their name, then the listing gets messed up. The SSID with a space gets split up as multiple entries within the whiptail menu. An example is that "Test Networks Network" would be 3 entries. Any help in fixing this issue, would be greatly appreciated.
The code in question is shown below. You'll notice I'm manually adding an "Other" to the list in order to allow for manual entry of SSIDs later.
wifiNetworkList="$(iwlist wlan0 scan | grep ESSID | awk -F \" '{print $2 ; print $2}')"
wifiNetworkList+=' Other Other'
wifiSSID=$(whiptail --notags --backtitle "PiAssist" --menu "Select WiFi Network" 20 80 10 $wifiNetworkList 3>&1 1>&2 2>&3)
Final Solution:
wifiNetworkList=() # declare list array to be built up
ssidList=$(iwlist wlan0 scan | grep ESSID | sed 's/.*:"//;s/"//') # get list of available SSIDs
while read -r line; do
wifiNetworkList+=("$line" "$line") # append each SSID to the wifiNetworkList array
done <<< "$ssidList" # feed in the ssidList to the while loop
wifiNetworkList+=(other other) # append an "other" option to the wifiNetworkList array
wifiSSID=$(whiptail --notags --backtitle "PiAssist" --menu "Select WiFi Network" 20 80 10 "${wifiNetworkList[@]}" 3>&1 1>&2 2>&3) # display whiptail menu listing out available SSIDs
I've included comments in the code to help explain what's going on to those that run into this same problem. One of the key things to note is that when we provide the wifiNetworkList to whiptail, we have to put quotes around it, which gives us "${wifiNetworkList[@]}"
.
Rather than building up a string with a variety of quoting, it’s easier to use an array. You basically are working with identical pairs that sometimes have spaces in a single entry.
I can’t reproduce the input with spaces, but from the point of grep
it can be fabricated with:
% echo 'ESSID:"net one"\nESSID:"net2"'
ESSID:"net one"
ESSID:"net2"
I’ll show the rest of this in Zsh since its array treatment (not splitting words) is cleaner, which you could port to Bash if Zsh is not an option for you.
This puts each essid e
into an array twice.
% l=() # declare list array to be built up
% print 'ESSID:"net one"\nESSID:"net2"' |
while read line; do e=$(sed 's/.*:"//;s/"//' <<<$line); l+=($e $e); done
Add other
twice:
% l+=(other other)
You can see that l
is now in a useful paired form:
% print -l $l
net one
net one
net2
net2
other
other
Now it’s a simple matter of calling whiptail
as you’ve done:
% wifiSSID=$(whiptail --notags --backtitle "PiAssist" --menu "Select WiFi Network" 20 80 10 $l)