LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 08-16-2012, 08:17 AM   #1
aswani
LQ Newbie
 
Registered: Jun 2011
Location: Bangalore, India
Distribution: Open SuSe11.4
Posts: 12

Rep: Reputation: Disabled
Bash Shell Script to check if a string has only alphabets and digits.


Hello,

I am trying to write a simple shell script. Here I want to pass a string to the script and want the script to check if the string has only alphabets and digits.

Code:
#!/bin/bash

# needs to be debugged

Rand_String=$1;

if  test $Rand_String = "[0-9A-Za-z]*"

        then echo "string $Rand_String has alphabets which are only alpha numeric";

        else echo "string $Rand_String has characters which are not alphanumeric";

fi
this script always says that the string has characters which are not alpha numeric. Please check where the error is.

best wishes,
Aswani
 
Old 08-16-2012, 08:42 AM   #2
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 651

Rep: Reputation: 269Reputation: 269Reputation: 269
you are comparing $Rand_String to the literal string "[0-9A-Za-z]*". If you want that to be interpreted as a pattern, you need to remove the double quotes. Also, bash globs are not regexp (at least not by default) so your pattern does not mean "an arbitrary number of alphanumeric characters", but "an alphanumeric character followed by arbitrary number of any characters." One way to do what you want might be something like this:

Code:
[[ "${Rand_String//[0-9A-Za-z]/}" = "" ]] && echo "Only contains alphanumeric" || echo "Contains other characters"
 
Old 08-16-2012, 08:44 AM   #3
cgmertens
LQ Newbie
 
Registered: May 2010
Posts: 1

Rep: Reputation: 1
#!/bin/bash

# This is one solution:
# 1) don't use test, it has very limited capabilities
# 2) added quoting to allow spaces in input string
# 3) use regular expression operator =~
# 4) use ^ "not in set" regexp operator
# 5) use + for one or more matches rather than * for zero or more

Rand_String="$1"

if [[ "$Rand_String" =~ [^0-9A-Za-z]+ ]] ; then
echo "string $Rand_String has characters which are not alphanumeric"
else
echo "string $Rand_String has alphabets which are only alpha numeric"
fi
 
1 members found this post helpful.
Old 08-16-2012, 09:06 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
How about this instead?

Code:
case ${string//[[:alnum:]]} in

	"") echo "all clean" ;;
	 *) echo "not clean" ;;

 esac
It strips out all alphanumeric characters, so if there's anything remaining, then it doesn't pass the test. And case statement globbing matches are generally more efficient than if statements, especially when using regexes.

Edit: a variation on the theme, perhaps easier to read:

Code:
case $string in

	*[^[:alnum:]]*) echo "not clean" ;;
	             *) echo "all clean" ;;

 esac

Last edited by David the H.; 08-16-2012 at 09:08 AM.
 
1 members found this post helpful.
Old 08-16-2012, 09:18 AM   #5
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,327

Rep: Reputation: 1099Reputation: 1099Reputation: 1099Reputation: 1099Reputation: 1099Reputation: 1099Reputation: 1099Reputation: 1099
Strictly speaking, the pattern needs to also include the beginning-of-string and end-of-string anchors as well. The pattern must be: "beginning-of-string, followed by zero-or-more occurrences of, say, :alnum:, followed by end-of-string." You might or might not need to use egrep to specify this "extended" regular expression.

One of the best things you can do is to spend a lot of time patiently studying the arcane art of regular-expressions ... which are actually "easy to understand but dammed hard to read." They are one of the great power-tools of the programming craft. Although the "string of gibberish" presentation of a regex is fairly confrontational, and the facility is full of (frankly, too many) arcane options, the concept is a simple one, and there are enormous very-practical applications for it. The knowledge will serve you very, very well. Oh yes, in the Windows world too.

Last edited by sundialsvcs; 08-16-2012 at 09:22 AM.
 
Old 08-16-2012, 09:33 AM   #6
aswani
LQ Newbie
 
Registered: Jun 2011
Location: Bangalore, India
Distribution: Open SuSe11.4
Posts: 12

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by millgates View Post
you are comparing $Rand_String to the literal string "[0-9A-Za-z]*". If you want that to be interpreted as a pattern, you need to remove the double quotes. Also, bash globs are not regexp (at least not by default) so your pattern does not mean "an arbitrary number of alphanumeric characters", but "an alphanumeric character followed by arbitrary number of any characters." One way to do what you want might be something like this:

Code:
[[ "${Rand_String//[0-9A-Za-z]/}" = "" ]] && echo "Only contains alphanumeric" || echo "Contains other characters"
Thanks for your reply. The code that you suggested works well.

However please note that when I remove the double quotes in my original script as mentioned by you, the script gives an error saying

Code:
[aswani@maruthi]$ test_string.sh abcd
test_string.sh: line 7: test: too many arguments
 
Old 08-16-2012, 09:46 AM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Quote:
Originally Posted by sundialsvcs View Post
Strictly speaking, the pattern needs to also include the beginning-of-string and end-of-string anchors as well. The pattern must be: "beginning-of-string, followed by zero-or-more occurrences of, say, :alnum:, followed by end-of-string." You might or might not need to use egrep to specify this "extended" regular expression.

That's not really correct here. All regex searches start implicitly from the beginning of the line. And the only thing we're interested in is whether there's at least one non-alphanumeric character as it walks towards the end in its search. So we don't even really need a repeater character here. All the "[]" bracket expression has to do is find a single a matching character and the regex returns true, otherwise false.

Globbing, BTW, is implicitly anchored at both ends, so the expression must take into account the whole string.

Code:
[[ $string =~ [^[:alnum:]] ]] && echo "not clean" || echo "clean"

[[ $string == *[^[:alnum:]]* ]] && echo "not clean" || echo "clean"

echo "$string" | grep -q '[^[:alnum:]]' && echo "not clean" || echo "clean"
Edit: incidentally, when using regex in bash's [[..]] test, properly escaping shell-reserved characters can be a problem. The best way to handle it is to store the regex in a separate variable first.

Code:
re='[^[:alnum:]]'
[[ $string =~ $re ]] && echo "not clean" || echo "clean"

Last edited by David the H.; 08-16-2012 at 09:50 AM. Reason: addendum
 
1 members found this post helpful.
Old 08-16-2012, 09:46 AM   #8
aswani
LQ Newbie
 
Registered: Jun 2011
Location: Bangalore, India
Distribution: Open SuSe11.4
Posts: 12

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by cgmertens View Post
#!/bin/bash

# This is one solution:
# 1) don't use test, it has very limited capabilities
# 2) added quoting to allow spaces in input string
# 3) use regular expression operator =~
# 4) use ^ "not in set" regexp operator
# 5) use + for one or more matches rather than * for zero or more

Rand_String="$1"

if [[ "$Rand_String" =~ [^0-9A-Za-z]+ ]] ; then
echo "string $Rand_String has characters which are not alphanumeric"
else
echo "string $Rand_String has alphabets which are only alpha numeric"
fi
thanks for the answer, the modified script works well.
 
Old 08-16-2012, 09:49 AM   #9
aswani
LQ Newbie
 
Registered: Jun 2011
Location: Bangalore, India
Distribution: Open SuSe11.4
Posts: 12

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by David the H. View Post
How about this instead?

Code:
case ${string//[[:alnum:]]} in

	"") echo "all clean" ;;
	 *) echo "not clean" ;;

 esac
It strips out all alphanumeric characters, so if there's anything remaining, then it doesn't pass the test. And case statement globbing matches are generally more efficient than if statements, especially when using regexes.

Edit: a variation on the theme, perhaps easier to read:

Code:
case $string in

	*[^[:alnum:]]*) echo "not clean" ;;
	             *) echo "all clean" ;;

 esac
Thanks for the answer, your explanation helped me to understand what is happening within your first script.
 
  


Reply

Tags
shell script


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to check folder if it has files in it using Bash Shell script vincent.dang Linux - Newbie 7 08-05-2010 07:58 PM
Check if actions in bash shell script are performed well proNick Linux - Newbie 6 02-09-2009 07:25 PM
BASH - convert single digits to double digits. rickenbacherus Programming 7 05-07-2008 06:53 AM
bash script to preserve only first digits alenD Linux - Software 6 04-14-2008 12:51 PM
Bash script to check the input string length fjkum Programming 3 06-30-2007 08:43 PM


All times are GMT -5. The time now is 07:37 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration