Building a dynamic UNIX menu with input files

Hi!

I am looking to build dynamic menu (named: lookup.sh) that reads a pipe delimited file for input.

for example, contents of input.txt could be:

user1|srv1
user3|srv1
user4|srv1
user2|srv2

I want the menu look like:

1) get password for user1 on srv1
2) get password for user3 on srv1
3) get password for user4 on srv1
4) get password for user2 on srv2
Choose Option:

then if you choose option #1, it would cat pass_user1_srv1.txt to provide the password.

the key thing I am trying to accomplish is that I don't want to modify lookup.sh when i add a new option. i want to go to the input.txt file and add a line to that and it will be read in the next time lookup.sh is run.

will a bash array work? I am not too familiar with them.

Any ideas?
Any help would be greatly appreciated!
Chris

What operating system and shell are you using?

If you're using a recent bash or ksh , have you considered select ?

#!/bin/bash

while [ -z "${ans[0]}" ]
do
  awk -F'|' '{print NR ") get password for " $1 " on " $2}' input.txt
  read -p "Choose Option Number: " sel
  ans=($(awk -F'|' 'NR==sel {print $1, $2}' sel="$sel" input.txt))
done
cat pass_${ans[0]}_${ans[1]}.txt
1 Like

RHEL 6 -- ksh or bash are available.

---------- Post updated at 09:52 PM ---------- Previous update was at 06:40 PM ----------

---------- Post updated at 09:59 PM ---------- Previous update was at 09:52 PM ----------

@rdrtx1 -- your code worked! Thank you very much!

Assuming bash or ksh are available, try

IFS=$'\n'
select ans in $(sed 's/^/get password for /; s/[|]/ on /' input.txt)
  do    T=${ans% on*}
        echo cat pass_${T##* }_${ans##* }.txt
  done
1) get password for user1 on srv1
2) get password for user3 on srv1
3) get password for user4 on srv1
4) get password for user2 on srv2

If you do use a select loop, remember that you will need to use break to get out of the select loop. I try to avoid break everywhere else because it can be ambiguous as to which loop is being stepped out of.

Just my two-penneth-worth,
Robin

Hi Robin,
The command:

break N

should break out of the innermost N (1 if N is not specified) enclosing for , while , until , and (in shells that implement select loops) select loops. You get varying behavior if you try to break out of more loops than you are currently in OR if you try to break out of a loop invoking a function using a break command inside that function's defining text, but if you're writing portable code you just shouldn't attempt to do either of those things.

Is there some other issue with break that has caused you problems?

Note that you can also exit a select loop by it hitting EOF on the file from which it is reading. So, if you are reading from a keyboard, you can add a choice to the selection list that is something like Enter ctl-D to exit when done if you want to avoid using break in a select statement. (But, it would usually be a good idea to add a break associated with that label in case the user enters the number associated with that selection instead of following directions and hitting ctl-D. :rolleyes: ) Or, you can set PS3 with something like:

PS3='Enter selection number (or ctl-D to exit): '

and avoid that possible confusion.

Hello Don,

Thanks for the comments.

I'm sure that break works exactly as designed, but I would guess my incompetence in keeping track of how many loops are in play is the reason, especially as code evolves and I add a loop round a section existing code. I remember to complete the indenting to help, but if I don't increment the break statement I don't step out where I was expecting to.

Like I say, I try to avoid it because I get it working then make a mess of it later. I'm not sure if using break for other loops is good programming practise or not, but I try to loop on clear conditions rather than just jump out part way through.

Kind regards,
Robin