6

example

#!/bin/bash

INSTALL_PATH="/usr/local"
BFGMINER_INSTALL_PATH="${INSTALL_PATH}/bfgminer"
BFGMINER_REPO="https://github.com/luke-jr/bfgminer.git"

list_last_ten_bfgminer_tags () {
    cd ${BFGMINER_INSTALL_PATH}
    git for-each-ref --format="%(refname)" --sort=-taggerdate --count=10 refs/tags | cut -c 6-
}

clone_bfgminer () {
    cd ${INSTALL_PATH}
    git clone ${BFGMINER_REPO} ${BFGMINER_INSTALL_PATH}
}

echo "select number to switch tag or n to continue"
select result in master $(list_last_ten_bfgminer_tags)
do

    # HOW DO I CHECK THE INDEX???????  <================================= QUESTION
    if [[ ${result} == [0-9] && ${result} < 11 && ${result} > 0 ]]
        then
            echo "switching to tag ${result}"
            cd ${BFGMINER_INSTALL_PATH}
            git checkout ${result}
    else
        echo "continue installing master"
    fi

    break
done

So if the user enters 1, the case statement checks for the match on the text, how can I match on 1 instead?

Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • Related and very useful: http://stackoverflow.com/a/226724/1983854 – fedorqui Mar 28 '14 at 13:30
  • @fedorqui thanks, I have seen this before and is a great post, I'm looking to see if I can access the bash select array by index – Phill Pafford Mar 28 '14 at 13:33
  • I don't understand your question, if the value were returned how would you know which answer was selected? You typically want the value and not the index which is the whole convenience of `select`. – Adrian Frühwirth Mar 28 '14 at 13:33
  • 1
    Please post some code indicating how you are populating the menu. It's difficult to suggest a solution without know the exact problem you are having. – chepner Mar 28 '14 at 13:34
  • @chepner updated with my code – Phill Pafford Mar 28 '14 at 13:39
  • @PhillPafford Please provide a minimal example, there is a lot of clutter in your code which we don't need to know about. – Adrian Frühwirth Mar 28 '14 at 13:40
  • @AdrianFrühwirth understandable, but the code is not that complicated and others asked how I was populating the select option. Looking at this: # HOW DO I CHECK THE INDEX??????? for the part I'm asking guidance with, Thanks for you time and effort – Phill Pafford Mar 28 '14 at 13:43

3 Answers3

15

Use the $REPLY variable

PS3="Select what you want>"
select answer in "aaa" "bbb" "ccc" "exit program"
do
case "$REPLY" in
    1) echo "1" ; break;;
    2) echo "2" ; break;;
    3) echo "3" ; break;;
    4) exit ;;
esac
done
clt60
  • 62,119
  • 17
  • 107
  • 194
  • 1
    +1 This definitely answer their question but OP is doing it in a very non-idiomatic way to begin with so I advise against doing this, it's just not necessary. – Adrian Frühwirth Mar 28 '14 at 13:45
  • 1
    @AdrianFrühwirth honestly, i'm readed only the title and the last scentence with the question. ;) So, youre probably right. ;) – clt60 Mar 28 '14 at 13:47
6

You don't need to check which value is selected; you can simply use it. The only thing you do want to check against is master, which is simple to do.

select result in master $(list_last_ten_bfgminer_tags)
do
    if [[ $result = master ]]; then
        echo "continue installing master"
    elif [[ -z "$result" ]]; then
        continue
    else
        echo "switching to tag ${result}"
        cd ${BFGMINER_INSTALL_PATH}
        git checkout ${result}
    fi
    break
done
Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71
chepner
  • 497,756
  • 71
  • 530
  • 681
  • no I get this, but what I they fat finger and enter in 23, it's not an option, how do I handle this? – Phill Pafford Mar 28 '14 at 13:47
  • 1
    You don't; `select` handles it for you. If you type `23`, and there is no option 23, `select` makes you enter another choice before it will enter the body. If there *is* a choice 23, well, how is your code suppose to distinguish between an intentional choice and a typo? – chepner Mar 28 '14 at 13:50
  • maybe I'm missing this, I'm testing the changes but it still ends if I select an option not on the menu – Phill Pafford Mar 28 '14 at 13:54
  • Sorry, I misinterpreted my own test. I'll fix the answer in a moment. Specifically, `result` will be set to the empty string if you make an invalid choice. (Adrian alluded to this, but deleted his comment, apparently.) – chepner Mar 28 '14 at 13:56
  • 2
    Thanks, that did it but I did need to move the break to inside the if and else – Phill Pafford Mar 28 '14 at 14:04
  • @chepner I deleted my comment since I trusted yours more than my own test, heh. – Adrian Frühwirth Mar 28 '14 at 14:35
  • @PhillPafford Ah, right. I replaced my comment with `continue` so you can have just one `break`. – chepner Mar 28 '14 at 14:38
4

I am struggling to understand your question but here is some example code; the array could be dynamically populated which I guess is where you are coming from:

$ cat t.sh
#!/bin/bash

foo=(one two three four)

echo "Please select an option: "
select reply in "${foo[@]}"; do
        [ -n "${reply}" ] && break
done
echo "You selected: ${reply}"

.

$ ./t.sh
Please select an option:
1) one
2) two
3) three
4) four
#? 5
#? 100
#? 2
You selected: two

How is this insufficient?

Of course, you could also use read and build the functionality yourself if you want the output/logics to differ from what select offers.

Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71
  • updated my question with more code, does this change your answer? – Phill Pafford Mar 28 '14 at 13:40
  • Not really, I still don't understand why you want/need the index. Your values are git tags and you want to do something with those tags, how is the select index relevant? As I demonstrated the variable set by select will be empty if no answer was selected, so if you enter an invalid value or just press enter you would continue your workflow installing master. You don't need to manually check if `$result` is within range. – Adrian Frühwirth Mar 28 '14 at 13:42
  • say the user enters in 30, there is no tag and I wanted to output a message, also if the user does not want to switch tags, I thought by validating with the index I could control the flow better. Also when I change to another repo, it might not have tags and or the tags will be named differently – Phill Pafford Mar 28 '14 at 13:46
  • If the use enters 30, `select` detects that is an invalid choice and prompts you again. – chepner Mar 28 '14 at 13:47
  • It doesn't matter if the tags will be named differently because you only need to check for the `master` case specifically and just use the result. – Adrian Frühwirth Mar 28 '14 at 13:48
  • @AdrianFrühwirth thanks for the help +1 as I think you also helped in leading me to the answer – Phill Pafford Mar 28 '14 at 14:13
  • @PhillPafford Thanks! I had posted my code before you posted yours and I was admittedly too lazy to update it with your concrete example after you had posted it, chepner's post after the edit reflects exactly what I had in mind so I'm glad we could provide you with a better solution together :-) – Adrian Frühwirth Mar 28 '14 at 14:38