If you are trying to write portable shell code, your options for string manipulation are limited. In the case construct, you can use globing wrapper patterns (which are much less expressive than regular expressions):
export LC_COLLATE=C read word while case "$word" in *[!A-Za-z]*) echo >&2 "Invalid input, please enter letters only"; true;; *) false;; esac do read word done
EDIT : LC_COLLATE necessary because most local non- C character ranges, such as AZ , do not have an “obvious” meaning. I assume that you want only ASCII letters; if you also want letters with diacritics, do not change LC_COLLATE and replace A-Za-z with [:alpha:] (so that the whole pattern becomes *[![:alpha:]]* ).
For full regular expressions, see the expr command. EDIT . Note: expr , like several other basic shell tools, has traps with some special lines; the z characters below allow $word interpreted as reserved words expr .
export LC_COLLATE=C read word while expr "z$word" : 'z[A-Za-z]*$' >/dev/null; then echo >&2 "Invalid input, please enter letters only" read word fi
If you are using only the latest versions of bash, there are other options, such as the =~ operator of conditional commands [[ ... ]] .
Please note that there is an error in your last line, the first command should be
grep -i "$word" "$1"
Quotations due to the fact that it is somewhat intuitive, "$foo" means "the value of a variable called foo ", whereas plain $foo means "take the value of foo , break it into separate words, where it contains spaces and process each word like a globe template and try to expand it. " (In fact, if you have already verified that $word contains only letters, leaving the quotation marks do no harm, but it takes more time to think about these special cases than just putting the quotation marks each time.)
Gilles
source share