Postcode help!

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
samip1983
Forum Newbie
Posts: 7
Joined: Thu Jul 28, 2005 9:57 am

Postcode help!

Post by samip1983 »

Hi all,

Im currently working on a piece of programming using perl, im using regex to manipulate incoming postcodes. Once entering the postcode a format is also used i.e. U for the postcode to be outputted as uppercase, and format=L for the output to be all lowercase. The problem is i am programming using if and ifels commands and it doesnt seem to work.

Any help would be great

rgds

Sami P
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

*magic ball*

The problem is with you (and your code). Many people have used if-else before without any problem ;)

Meaby if you post some code, explain it what it does (or what it should do) and then we can help you...
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

CGI or command line? I don't really understand what you're asking and it's beeen a while since I wrote any perl (ifels? you mean elsif?)...

Code: Select all

#!/usr/bin/perl

print &quote;Enter postcode: &quote;;
$postcode = <STDIN>; #Take input from STDIN
trim;

if ($postcode =~ /їa-z]{1,2}\d{1,2}\s*\dїa-z]{2}/i) #That's UK postcode
{
    print &quote;\nEnter U for uppercase or L for lowercase: &quote;;
    $case = <STDIN>;
    trim;
    
    if ($case == &quote;u&quote; || $case == &quote;U&quote;)
    {
        print uc($postcode).&quote;\n&quote;; #Why?
    }
    elsif ($case == &quote;l&quote; || $case == &quote;L&quote;)
    {
        print lc($postcode).&quote;\n&quote;;
    }
    else
    {
        print &quote;You didn't enter U or L\n&quote;;
    }
}
else
{
    print &quote;That postcode isn't valid\n&quote;;
}
EDIT | Got bored, tested it and fixed the syntax errors ;)
samip1983
Forum Newbie
Posts: 7
Joined: Thu Jul 28, 2005 9:57 am

Post by samip1983 »

Hi thanks for the replys,

So far i have got some bit working, U = uppercase L = lowercase SP = a space between the postcode, if it is entered together and NS = no space if the postcode is entered with a space.
Some of aspects work and some are just baffeling me in the way they are not working. An example being the if a post code is inputted with a space and the U format is entered in returns an invalid output??

Code: Select all

#!/usr/bin/perl
use strict;
use CGI ':standard';

my ($postcode, $format, $up, $down, $cut, $lft, $rgt, $rigt);

$postcode = param('postcode');
$format = param('format');

$up = param '';
$down = param '';

$up = uc($postcode);
$down= lc($postcode);
#$cut= chop($postcode);
$lft= substr($postcode, 0, 3);
$rgt= substr($postcode, 3, 4);
$rigt = substr($postcode, 3, 7);

print &quote;content-type: text/html\n\n&quote;;

if (  $postcode =~ /\D{2}\d{1,2}\s\d\D{2}/ && $format eq &quote;NS&quote; || $format eq &quote;ns&quote;) {
$postcode =~ s/ //g;

print &quote;$postcode\n&quote;; 

}

elsif ( $postcode =~ /\D{2}\d{1,2}\s*\d\D{2}/g && $format =~/U/) {
print &quote;$up\n&quote;;

}
elsif ( $postcode =~ /\D{2}\d{1,2}\s\d\D{2}/ || $format eq &quote;SP&quote; || $format eq &quote;sp&quote;) {
print &quote;$lft $rgt\n&quote;; 

}
elsif ( $postcode =~ /\D{2}\d{1,2}\s*\d\D{2}/ && $format =~/L/)  {
print &quote;$down\n&quote;;

}

elsif ( $postcode =~ /\D{2}\d{1,2}\s*\d\D{2}/ || $format =~/ /) {
print &quote;$postcode\n&quote;;


}
else
{

  print &quote;Invalid Data\n&quote;;
}
I was wondering if anyone knoew any simpler way to introduce the different formats rather than using the if and elsif beginnings?

any help would be appreciated

thanks

sami p
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

if..elsif..else makes perfect sense to me. I wouldnt change that. The only other way to *sometimes* do things like that is to use a switch() condition but that wont work here because of the conditions in each of your steps here.

<side note>
Thanks for reminiding me how nice a language perl is again.
(and that it's "eq" not "==" when dealing with string literals :))
</side note>

Your regex could certainly be improved however.... they will match a postcode yes but they dont represent the actual pattern a postcode takes (we are talking about UK postcodes I assume from looking at your code?).

Might be an idea to drop the

$format eq "NS" || $format eq "ns"

and replace it with

lc($format) eq "ns" ;)

Also, this could explain your problem with getting "Invalid input"...

$format =~/L/

It's case sensitive (and why do a perl re on a single character?)..


Try replacing it with:

lc($format) eq "l"

Code: Select all

#!/usr/bin/perl
use strict;
use CGI ':standard';
 
my ($postcode, $format, $up, $down, $cut, $lft, $rgt, $rigt);
 
$postcode = param('postcode');
$format = param('format');
 
$up = param '';
$down = param '';
 
$up = uc($postcode);
$down= lc($postcode);
#$cut= chop($postcode);
$lft= substr($postcode, 0, 3);
$rgt= substr($postcode, 3, 4);
$rigt = substr($postcode, 3, 7);
 
print &quote;content-type: text/html\n\n&quote;;
 
if (  $postcode =~ /&#1111;a-z]{2}\d{1,2}\s\d&#1111;a-z]{2}/i && lc($format) eq &quote;ns&quote;) {
$postcode =~ s/ //g;
 
print &quote;$postcode\n&quote;; 
 
}
 
elsif ( $postcode =~ /&#1111;a-z]{2}\d{1,2}\s*\d&#1111;a-z]{2}/i && lc($format) eq &quote;u&quote;) {
print &quote;$up\n&quote;;
 
}
elsif ( $postcode =~ /&#1111;a-z]{2}\d{1,2}\s\d&#1111;a-z]{2}/i || lc($format) eq &quote;sp&quote;) {
print &quote;$lft $rgt\n&quote;; 
 
}
elsif ( $postcode =~ /&#1111;a-z]{2}\d{1,2}\s*\d&#1111;a-z]{2}/i && lc($format) eq &quote;l&quote;)  {
print &quote;$down\n&quote;;
 
}
 
elsif ( $postcode =~ /&#1111;a-z]{2}\d{1,2}\s*\d&#1111;a-z]{2}/i || $format =~/^$/) {
print &quote;$postcode\n&quote;;
 
 
}
else
{
 
  print &quote;Invalid Data\n&quote;;
}
I can probably post a method that utilises regex a bit better though (backreferences rather than using substr() since you have the patterns available) ;)
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

It has been ages since i've done some Perl, but i've been told the following ;)

Instead of using (show warnings)

Code: Select all

#!/bin/perl -w
use:

Code: Select all

#!/bin/perl

use warnings;
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Ignore my statement about using a swicth too... it doesnt appear to work in perl lol...

You got me playing with it now :P

Same here timvw... I think i last touched it 3 years ago... best way to learn regex though ;)

TIP: Add ^ and $ to the start and end of your patterns... you're letting invalid data in at the start and end the way you have it ;)

Code: Select all

/^(&#1111;a-z]{2}\d{1,2})(\ *)(\d&#1111;a-z]{2})$/i
Notice I added the parens... you can get everything out of those rather than using substr() ;)
Last edited by Chris Corbyn on Thu Jul 28, 2005 6:17 pm, edited 2 times in total.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

perl5.8 seems to support switch ;)

http://perl.active-venture.com/lib/Switch.html (woow, the first version i used was 4.x)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Ah I have 5.8.5, the syntax must be different to what I thought cheers... i'll have a read up.

samip1983 unless your query is specifically over the regex then we dont really deal with perl (although you got me started now :))...

EDIT | Yes the syntax is not like that of PHP switch()... needs curlies { } and no colon : :)
samip1983
Forum Newbie
Posts: 7
Joined: Thu Jul 28, 2005 9:57 am

Post by samip1983 »

Thanks for all your replys, at work at the moment so ill have a play with iut later......hopefully get it working, the main think thats annoying me is the spacing once ns or sp is entered as a format. it only works when there is a postcode like cv16sy, but doest work if the postcode is like cv116sy.

But i think the change in regex has made a difference, thanks.

cheers.....
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

That is because you only accept 1 or 2 numbers.. \d{1,2}

If you want to allow 1-2 or 3 make that \d{1,3}
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

timvw wrote:That is because you only accept 1 or 2 numbers.. \d{1,2}

If you want to allow 1-2 or 3 make that \d{1,3}
Adding parens like I did should seperate them out anyway (then you can access the LHS and RHS using the backreferences $1 and $2 and $3)...
samip1983
Forum Newbie
Posts: 7
Joined: Thu Jul 28, 2005 9:57 am

Post by samip1983 »

Hi,

i wasnt aware you could access the postcode using lhs and rhs, this might be easier to use the spacing formats ns-no space sp-space.

i was wondering using the code below

Code: Select all

elsif ( $postcode =~ /&#1111;a-z]{2}\d{1,2}\s*\d&#1111;a-z]{2}/i && lc($format) eq &quote;l&quote;)  {print &quote;$down\n&quote;;
why is there lc before the format, i know it means lower case but i need the case depending on what format the user enters.

thanks guys
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Well it's lowercase of whatever the user enters comparing against lowercase "l" or "u"... so if upper or lowercase L or U is typed then it still matches.

for example:

Code: Select all

$foo = &quote;BAR&quote;;

if (lc($foo) eq &quote;bar&quote;) print $foo;
Saves doing:

Code: Select all

$foo = &quote;BAR&quote;;

if ($foo eq &quote;BAR&quote; || $foo eq &quote;bar&quote;) print $foo;
Post Reply