Validating a string

I’m still trying to teach myself Python and have come unstuck at validating a string. I want to check that a string contains nothing but alpha (upper or lower), space, single quote or hyphen.

I guess I could have a string containing all the valid characters and check each character in the input string using a for loop, but that seems rather inefficient…

Edit: Python 3 (of course!) :slight_smile:

A regular expression would be more efficient.

import re

p = re.compile('[^a-zA-Z\s\-\']')
p.match(input_string)

If p.match returns anything except None, then it has invalid characters and you will want to reject it.

1 Like

Cool, thanks @cpradio for the answer and the link. I Googled for regex but found nowt.

I must be doing something wrong here as it always prints Mr Nobody even when both x1 and x2 are None

print("Content-type:text/html\r\n")

# Import modules for CGI handling and regex
import cgi, cgitb, re

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

# Validate
p = re.compile('[^a-zA-Z\s\-\']')
x1 = p.match(first_name)
x2 = p.match(last_name)
#print(x1, x2)
print('''<!doctype html>
<html lang="en-gb">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello World - Second Python Program</title>
</head>
<body>''')
if (x1 == 'None') and (x2 == 'None') :
    print("<h1>Hello %s %s</h1>" % (first_name, last_name))
else :
    print('<h1>Hello Mr Nobody</h1>')
print('''</body>
</html>''')

Match doesn’t work that way. It returns a position (starting at 0) where a match to the pattern is.

So you want something like (I’m guessing - I don’t know python…)…

if (x1 < 0) and (x2 < 0) :
1 Like

Not in Python it doesn’t. But I’m going based on the documentation here

If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding MatchObject instance. Return None if the string does not match the pattern; note that this is different from a zero-length match.

source: https://docs.python.org/2/library/re.html

The problem is you are using ‘None’, instead of None.

if (x1 == None) and (x2 == None) : 

None is a “special class” in Python.

1 Like

Bah…documentation. Who reads that? :wink:

That makes sense, even more than the -1 that all other languages seem to use…

Ah. Daylight begins to dawn on one small brain cell…

Okay, now I have the following. It tells me ?Gandalf is invalid but it allows Gandalf? so I assume I have the regex expression wrong. My knees (and brain) go to jelly at the sight of a regex!

print("Content-type:text/html\r\n")

# Import modules for CGI handling and regex
import cgi, cgitb, re

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

# Validate
p = re.compile('[^a-zA-Z\s\-\']')
x1 = p.match(first_name)
x2 = p.match(last_name)

print('''<!doctype html>
<html lang="en-gb">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello World - Second Python Program</title>
<link rel="stylesheet" href="hello.css">
</head>
<body>''')
if x1 != None:
    print('<p>First name is invalid</p>')
if x2 != None:
    print('<p>Last name is invalid</p>')
if x1 == None and x2 == None:
    print("<h1>Hello %s %s</h1>" % (first_name, last_name))
print('''</body>
</html>''')

Edit: Ah-ha I think replacing match with search does the trick. More testing needed…

1 Like

Yup, change .match to .search, if I read the docs closer I would have caught that sooner, .match is based on the beginning of the string, not “anywhere in the string”, .search on the other hand will solve this issue nicely.

Edit: Just saw your edit :slight_smile: Great minds and all that jazz :wink:

1 Like

Guess wot? I read the documentation! :smiley: Mind you, there’s so much I was lucky to find it! :wink:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.