Find the answer to your Linux question:
Results 1 to 4 of 4
Hi, I have a function to generate a menu dynamically from an array which can be seen here:- Code: function loadkeys { keys=( "key1" "key2" "key3") clear n=1 for i ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Sep 2010
    Posts
    18

    Bash: Dynamic case from variables


    Hi,

    I have a function to generate a menu dynamically from an array which can be seen here:-

    Code:
    function loadkeys {
    keys=( "key1" "key2" "key3")
    	clear
    	n=1
    	for i in "${keys[at_symbol]}"
    	do
    		echo -ne "$n) $i"
    			if [ $(ssh-add -l | grep -o "$i" | wc -l) -eq 1 ]; then
    				echo " [loaded]"
    			else
    				echo ""
    			fi
    		let n="$n+1"
    	done
    	echo ""
    	echo "$n) Unload all keys"
    	echo "0) Main Menu"
    	read category
    }
    Normally I would use a case statement to read in and take action from the user input. I would however like to generate the case based on the array, something similar to:-

    Code:
    case "$category" in
    
    		1) ssh-add ~/.ssh/key1;mainmenu;;
    		2) ssh-add ~/.ssh/key2;mainmenu;;
    		3) ssh-add ~/.ssh/key3;mainmenu;;
    		4) ssh-add -D; mainmenu;;
    		0) mainmenu;;
    esac
    Whats the best way to achieve this?

  2. #2
    Just Joined!
    Join Date
    Sep 2010
    Posts
    18
    Any ideas?

  3. #3
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    11,158
    You could write the case block to a file in a bash function body, and then include the file with a . command. IE:

    [code]
    # write case block inside doMenu() function to external file
    .
    .
    .
    # read doMenu() function from external file
    . doMenu.txt

    # Now, you can call doMenu
    .
    .
    .
    [code]
    Haven't tried that approach, here is an example that works.
    Code:
    #!/bin/bash
    cat >test.txt <<EOF
    doMenu()
    {
    case "\$1" in
        1) echo "do 1"    ;;
        2) echo "do 2"    ;;
        0) echo "do main" ;;
        *) echo "\$1 not found" ;;
    esac
    }
    EOF
    
    . test.txt
    
    doMenu 0
    doMenu 2
    doMenu 1
    doMenu 9
    Note that in the output operation you need to escape the $ in the variable names where used, as in "\$1" instead of "$1", otherwise bash will try to expand the variable when generating the function file.

    And thanks for making me think this up. It can come in handy!
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  4. #4
    Trusted Penguin
    Join Date
    May 2011
    Posts
    4,307
    Quote Originally Posted by harveyd View Post
    Any ideas?
    Well, here's one, based off of what you've posted...it uses your array to dynamically create a user-input-driven menu:
    Code:
    #!/bin/bash
    
    clear
    
    declare -a keys
    keys=('key1' 'key2' 'key3')
    declare -i i
    echo "0) Main Menu"
    for (( k=0;k<${#keys[*]};k++)) do
      i=$(( $k + 1 ))
      key=${keys[$k]}
      echo "$i) Add key \`$key'"
    done
    let i+=1
    echo "$i) Unload all keys"
    
    
    until [ -n "$category" ]; do
      echo -en "\nEnter a selection: "
      read category
      case $category in
        *) 
          if [ -z "$category" ]; then
            unset category
          else
            echo $category|grep -q ^[0-9]*$
            if [ $? -ne 0 ]; then
              echo "Selection \`$category' is invalid"
              unset category
            else
              if [ $category -eq $(( ${#keys[*]} + 1 )) ]; then
                cmd='ssh-add -D'
              elif [ $category -eq 0 ]; then
                cmd='gotomainmenu'
              else
                key=${keys[$(($category-1))]}
                if [ -z "$key" ]; then
                  echo "Selection \`$category' is invalid"
                  unset category
                else
                  cmd="ssh-add ~/.ssh/$key"
                fi
              fi
            fi
          fi
      esac
    done
    
    [ -z "$cmd" ] && echo "This cannot be!  cmd should have been defined" && exit 1
    
    echo -e "\nRunning command: \`$cmd'"
    eval $cmd
    exit $?
    I'm not sure i've got your ssh-add commands correct, and you'll have to add in your mainmenu stuff.

    Btw, you should not call your function loadkeys as that is a binary program that is commonly installed in Linux (part of the kbd package) and can be found in /bin/loadkeys. It probably won't cause your program any heartache, but it is always better to not have conflicting functions/programs, where possible.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •