2

I have this snippet: The logic behind it, is that I want the user to enter -s followed by a word (e.g. -s dog). However, it doesn't work.

read -rp 'choose: ' choice 
case $choice in 
     -a) echo you chose a;;
     -s [a-z]+) echo you chose the word ${choice#"-s "};;
esac

Thank you very much!!!

1

If you want to read two words using read, then use two variables:

read -r -p 'Enter "-a" or "-s <word>": ' opt word
case $opt in
    -a)
        echo 'You picked "-a"'
        ;;
    -s) 
        printf 'You picked "-s" with the word "%s"\n' "$word"
        ;;
    *)
        echo 'You picked neither "-a" nor "-s <word>"'
esac

The reason your code is not working is because you are using an extended regular expression as the pattern (-s [a-z]+). The patterns used by the case statement are filename globbing patterns. They are similar but not the same. A globbing pattern does not allow for the same sort of "repetition modifier" that a regular expression pattern uses (the +).

With a globbing pattern, you would be able to use '-s '[a-z]*, i.e. "the string -s  followed by a lower case letter, and then something" (the same as ^-s [a-z].* with a regular expression).

  • thank you for answering but this is a smaller part of a bigger project and the word has to be next to the -s parameter. How can I do the same thing but in the -s ...) bracket? – MargaritaK Dec 15 '19 at 21:18
  • @MargaritaK See updated answer, which contains a suggestion. I'm not sure what you mean by "next to". The user would enter a string, like -s someword. Here, -s is "next to" someword. I'm also a bit confused why you are using read to read things that look like command line options. – Kusalananda Dec 15 '19 at 21:22
  • thank you so much, I tried the 'opt word' and it seems to be working properly. I'm new to shell programming so that's why I used read to read these things. It's also a rule that I have to follow for the project – MargaritaK Dec 15 '19 at 21:26
0

There can not be an (unquoted) space on the …) part of a case statement.

So, you need to quote it: \, " " or ' ':

Also, the matching on case statements is done by patterns, not regexes. There is no + in Pattern Matching, there is only *, but that doesn't mean repetition of last element but simply "any character in any count". I'll assume that your [a-z]+ was intended to match a word made of only lowercase letters. It is not possible to write the same in simpler pattern matching strings. What could be done is:

read -rp 'choose: ' choice 
case $choice in 
     -a)           echo "you chose a";;
     -s\ *[^a-z]*) echo "not a valid word selected";;
     -s\ *)        echo "you chose the word ${choice#"-s "}";;
     *)            echo "no choice made";;
esac
  • @Freddy, thank you for answering!! How can I make the command have this input and still work? (e.g. user input: -d\ * -r) echo the word is ${choice#"-d -r"};; – MargaritaK Dec 16 '19 at 10:12
  • thank you for answering!! How can I make the command have this input and still work? (e.g. user input: -d\ * -r) echo the word is ${choice#"-d -r"};; – MargaritaK Dec 16 '19 at 10:12
0

You need to escape the space character (like in the answer to your previous question).

Bash interprets the + as a literal + and not as "one or more occurrences". Bash's pattern matching operators are different from regular expressions. To match one or more occurrences, you could enable the "extended globbing" extglob shell option and use the +(...) pattern.

To make sure the range expression [a-z] only matches lowercase letters (this might depend on your locale's LC_COLLATE or LC_ALL setting), you could also enable the globasciiranges shell option.

shopt -s extglob
shopt -s globasciiranges

read -rp 'choose: ' choice
case $choice in
     -a)
        echo "you chose a"
        ;;
     -s\ +([a-z]))
        echo "you chose the word \"${choice#-s }\""
        ;;
     *) echo "unknown choice \"$choice\""
esac

Related:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.