Check a string to see if it contains a numeric character on UNIX

I am new to UNIX, only running it at work today, but experienced in Java and having the following code:

#/bin/bash echo "Please enter a word:" read word grep -i $word $1 | cut -d',' -f1,2 | tr "," "-"> output 

This works great, but now I need to check, when the word is read, that it contains only letters, and if it has numeric characters in the print "Invalid input!" and ask them to enter it again. I assumed that regular expressions with an if statement would be an easy way to do this, but I can't figure out how to use them on UNIX, as I'm used to using them in Java. Any help with this would be greatly appreciated since I could not find help finding as all the regular expression solutions in linux that I found only if they were either numerical or not.

+7
string unix bash regex if-statement
source share
7 answers

Another approach. Grep exits with 0 if a match is found, so you can check the exit code:

 echo "${word}" | grep -q '[0-9]' if [ $? = 0 ]; then echo 'Invalid input' fi 

This is /bin/sh compatible.


Including the sentences of Daenyth and John, it becomes

 if echo "${word}" | grep '[0-9]' >/dev/null; then echo 'Invalid input' fi 
+17
source share

The double-bracket operator is an extended version of the test command that supports regular expressions using the =~ operator:

 #!/bin/bash while true; do read -p "Please enter a word: " word if [[ $word =~ [0-9] ]]; then echo 'Invalid input!' >&2 else break fi done 

This is a bash-specific function. Bash is a newer shell that is not available in all UNIX variants - although by “newer” I mean “only recently developed in the post-vacuum era” and “not all UNIX tastes”. I mean relics like older versions of Solaris and HP-UX.

In my opinion, this is the easiest option, and Bash is much portable today, but if transferring it to old UNIX files is really important, you need to use sh-compatible answers from other posters. sh is the most common and most widespread shell, but the price you pay for portability loses things like =~ .

+7
source share

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.)

+3
source share

Another (quite) portable way to do this ...

 if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then echo invalid fi 
+1
source share

One portable (assuming bash> = 3) way to do this is to remove all numbers and check the length:

 #!/bin/bash read -p "Enter a number" var if [[ -n ${var//[0-9]} ]]; then echo "Contains non-numbers!" else echo "ok!" fi 

Based on Java, it is important to note that bash does not have a real concept of objects or data types. This is all a line, and complex data structures are painful at best.

For more information on what I have done and other related functions, google for bash string processing.

0
source share

Playing with the Bash parameter extension and character classes:

 # cf. http://wiki.bash-hackers.org/syntax/pe word="abc1def" word="abc,def" word=$'abc\177def' # cf. http://mywiki.wooledge.org/BashFAQ/058 (no NUL byte in Bash variable) word=$'abc\000def' word="abcdef" ( set -xv [[ "${word}" != "${word/[[:digit:]]/}" ]] && echo invalid || echo valid [[ -n "${word//[[:alpha:]]/}" ]] && echo invalid || echo valid ) 
0
source share

Each answer seems to be based on the fact that the only invalid characters are numbers. The initial questions say that they need to check that the string contains "nothing but letters."

I think the best way to do this is

 nonalpha=$(echo "$word" | sed 's/[[:alpha:]]//g') if [[ ${#nonalpha} -gt 0 ]]; then echo "Invalid character(s): $nonalpha" fi 

If you find that this page is looking for a way to detect non-numeric characters in your string (for example, I did!), Replace [[: alpha:]] with [[: digit:]].

0
source share

All Articles