Checking a string to see if it contains numeric character in UNIX
Yet another approach. Grep exits with 0
if a match is found, so you can test the exit code:
echo "${word}" | grep -q '[0-9]'if [ $? = 0 ]; then echo 'Invalid input'fi
This is /bin/sh
compatible.
Incorporating Daenyth and John's suggestions, this becomes
if echo "${word}" | grep '[0-9]' >/dev/null; then echo 'Invalid input'fi
The double bracket operator is an extended version of the test
command which supports regexes via the =~
operator:
#!/bin/bashwhile true; do read -p "Please enter a word: " word if [[ $word =~ [0-9] ]]; then echo 'Invalid input!' >&2 else break fidone
This is a bash-specific feature. Bash is a newer shell that is not available on all flavors of UNIX--though by "newer" I mean "only recently developed in the post-vacuum tube era" and by "not all flavors of UNIX" I mean relics like old versions of Solaris and HP-UX.
In my opinion this is the simplest option and bash is plenty portable these days, but if being portable to old UNIXes is in fact important then you'll need to use the other posters' sh-compatible answers. sh is the most common and most widely supported shell, but the price you pay for portability is losing things like =~
.
If you're trying to write portable shell code, your options for string manipulation are limited. You can use shell globbing patterns (which are a lot less expressive than regexps) in the case
construct:
export LC_COLLATE=Cread wordwhile case "$word" in *[!A-Za-z]*) echo >&2 "Invalid input, please enter letters only"; true;; *) false;; esacdo read worddone
EDIT: setting LC_COLLATE
is necessary because in most non-C
locales, character ranges like A-Z
don't have the “obvious” meaning. I assume you want only ASCII letters; if you also want letters with diacritics, don't change LC_COLLATE
, and replace A-Za-z
by [:alpha:]
(so the whole pattern becomes *[![:alpha:]]*
).
For full regexps, see the expr
command. EDIT: Note that expr
, like several other basic shell tools, has pitfalls with some special strings; the z
characters below prevent $word
from being interpreted as reserved words by expr
.
export LC_COLLATE=Cread wordwhile expr "z$word" : 'z[A-Za-z]*$' >/dev/null; then echo >&2 "Invalid input, please enter letters only" read wordfi
If you only target recent enough versions of bash, there are other options, such as the =~
operator of [[ ... ]]
conditional commands.
Note that your last line has a bug, the first command should be
grep -i "$word" "$1"
The quotes are because somewhat counter-intuitively, "$foo"
means “the value of the variable called foo
” whereas plain $foo
means “take the value of foo
, split it into separate words where it contains whitespace, and treat each word as a globbing pattern and try to expand it”. (In fact if you've already checked that $word
contains only letters, leaving the quotes won't do any harm, but it takes more time to think of these special cases than to just put the quotes every times.)