1

I am trying to make a script to get ip list from file and show it on screen with select option, and make ssh to that IP just by selecting. File is like below;

name1 1.1.1.1 
name2 2.2.2.2
name3 3.3.3.3
name4 4.4.4.4

Below script can read the list from file and shows it on screen as menu.It show both name and IPs for selection, but I want to show selection menu just by name. How can I achieve this?

PS3='Please enter your choice: '
readarray -t options < ./file.txt

select opt in "${options[@]}"
do
IFS=' ' read name ip <<< $opt
case  $opt  in  
       $opt) ssh $ip;; 

esac
done

1) name1 1.1.1.1
2) name2 2.2.2.2
3) name3 3.3.3.3
4) name4 4.4.4.4
Please enter your choice: 1
  • You've tagged your question [tag:sh], but you're using a command `readarray` which does not exist in POSIX shell. Are you sure this isn't a [tag:bash] question? – ghoti Mar 07 '16 at 05:17
  • My guess is you are using a version of `bash` prior to 4.3, which had a bug which required `$opt` to be quoted in the here string for splitting to occur properly. Try `IFS=' ' read name ip <<< "$opt"`. – chepner Mar 08 '16 at 19:07
  • (To clarify, your code should work fine in `bash` 4.3 or later.) – chepner Mar 08 '16 at 19:10
  • (See http://stackoverflow.com/a/20163550/1126841) – chepner Mar 08 '16 at 19:22

2 Answers2

1

I'm assuming this is bash, not sh.

The select command isn't so frequently used. The problem you're having is that you're slurping whole lines in to $options with readarray, and the select command doesn't provide you with a way to format or trim the output.

One approach would be to split the array after reading it:

#!/usr/bin/env bash

declare -a opt_host=()   # Initialize our arrays, to make sure they're empty.
declare -A opt_ip=()     # Note that associative arrays require Bash version 4.
readarray -t options < ./file.txt

for i in "${!options[@]}"; do
  opt_host[$i]="${options[$i]%% *}"             # create an array of just names
  opt_ip[${opt_host[$i]}]="${options[$i]#* }"   # map names to IPs
done

PS3='Please enter your choice (q to quit): '
select host in "${opt_host[@]}"; do
  case "$host" in
    "") break ;;  # This is a fake; any invalid entry makes $host=="", not just "q".
    *) ssh "${opt_ip[$host]}" ;;
  esac
done
ghoti
  • 45,319
  • 8
  • 65
  • 104
0

Your code is correct, but to work around a bug in bash 4.0, 4.1, and 4.2, you need to quote the parameter expansion in the here string.

IFS=' ' read name ip <<< "$opt"
chepner
  • 497,756
  • 71
  • 530
  • 681