2010-02-18 6 views
1

Je dois créer une boucle, et avec une expression rationnelle remplir l'une des 4 variablesadresse Parse avec regex

$address, $street, $town, $lot 

La boucle sera alimenté une chaîne qui peut avoir d'info en elle comme les lignes ci-dessous

  • '123 any street, mytown' ou
  • 'Lot 4 another road, thattown' ou
  • 'Lot 2 96 other road, her town' ou
  • 'this ave, this town' ou
  • 'yourtown'

puisque tout après une virgule est le $town je pensais

(.*), (.*) 

alors la première capture pourrait être vérifiée avec (Lot \d*) (.*), (.*) si la 1ère capture commence par un nombre , puis son l'adresse (si le mot avec un espace blanc est $street) si un mot, c'est juste le $town

+0

Voir aussi http://stackoverflow.com/questions/642602/regular-expression- pour-parsing-mailing-adresses http://stackoverflow.com/questions/16413/parse-usable-street-address-city-state-zip-from-a-string etc –

Répondre

7

Jetez un oeil à Geo::StreetAddress::US si ceux-ci sont des adresses américaines.

Même si ce n'est pas le cas, la source de ce module devrait vous donner une idée de ce qui est impliqué dans l'analyse des adresses de rue libres.

Voici un script qui gère les adresses que vous (posté, mise à jour version antérieure lot combiné et numéro dans une chaîne):

#!/usr/bin/perl 

use strict; use warnings; 

local $/ = ""; 

my @addresses; 

while (my $address = <DATA>) { 
    chomp $address; 
    $address =~ s/\s+/ /g; 
    my (%address, $rest); 
    ($address{town}, $rest) = map { scalar reverse } 
         split(/ ?, ?/, reverse($address), 2); 

    { 
     no warnings 'uninitialized'; 
     @address{qw(lot number street)} = 
      $rest =~ /^(?:(Lot [0-9]))?(?:([0-9]+))?(.+)\z/; 
    } 
    push @addresses, \%address; 
} 

use Data::Dumper; 
print Dumper \@addresses; 

__DATA__ 
123 any street, 
mytown 

Lot 4 another road, 
thattown 

Lot 2 96 other road, 
her town 

yourtown 

street, 
town 

Sortie:

$VAR1 = [ 
      { 
      'lot' => undef, 
      'number' => '123', 
      'street' => 'any street', 
      'town' => 'mytown' 
      }, 
      { 
      'lot' => 'Lot 4', 
      'number' => undef, 
      'street' => 'another road', 
      'town' => 'thattown' 
      }, 
      { 
      'lot' => 'Lot 2', 
      'number' => '96', 
      'street' => 'other road', 
      'town' => 'her town' 
      }, 
      { 
      'lot' => undef, 
      'number' => undef, 
      'street' => undef, 
      'town' => 'yourtown' 
      }, 
      { 
      'lot' => undef, 
      'number' => undef, 
      'street' => 'street', 
      'town' => 'town' 
      } 
     ];
7

Je suggère que vous n'essayez pas de faire tout cela dans une seule expression rationnelle car il sera difficile de vérifier son exactitude.

D'abord, je diviserais à la virgule. Tout ce qui vient après la virgule est la ville $, et s'il n'y a pas de virgule, toute la chaîne est la ville $.

Ensuite, je vérifie s'il y a beaucoup d'informations et extrait de la chaîne. Ensuite, je chercherais le numéro et le nom de la rue/de l'avenue.

Divide and Conquer :)

1

Cela devrait se séparer en 3 parties - comment distinguez-vous l'adresse/rue?

(Lot \d*)? ?([^,]*,)? ?(.*) 

ici est la ventilation par vos exemples

('', '123 any street,', 'mytown') 
('Lot 4', 'another road,', 'thattown') 
('Lot 2', '96 other road,', 'her town') 
('', 'this ave,', 'this town') 
('', '', 'yourtown') 

Si je comprends bien, celui-ci sépare l'adresse/rue ainsi

(Lot \d*)? ?(\d*) ?([^,]*,)? ?(.*) 

('', '123', 'any street,', 'mytown') 
('Lot 4', '', 'another road,', 'thattown') 
('Lot 2', '96', 'other road,', 'her town') 
('', '', 'this ave,', 'this town') 
('', '', '', 'yourtown') 
+0

Numéros de maison ne sont pas si simples, ils peuvent avoir des lettres après eux (ou même IIRC avant eux) ou 1/2 et autres après eux – ysth

+0

@ysth, Nous testons des cas pour couvrir ceux-là alors.étendre l'expression rationnelle n'est pas si difficile - deviner les exigences est. –

0

Je ne peux pas correspondre à la dernière mais pour les 3 premiers, vous pouvez utiliser quelque chose comme ceci:

if (preg_match('/(?:Lot (\d*)|)(?: |)(?:(\d*)|) (.*), (.*)/m', $subject, $regs)) { 
    $result = $regs[1]; 
} else { 
    $result = ""; 
} 

c'est le test regex:

(?:Lot (\d*)|)(?: |)(?:(\d*)|) (.*), (.*) 

Vous pouvez l'utiliser dans RegexBuddy à tester: link

0

Geo :: StreetAddress :: Les États-Unis conviennent aux adresses simples, mais ils peuvent perdre du contexte sur des exemples plus difficiles. Il va analyser les noms des rues jusqu'à ce qu'il trouve une banlieue. Donc, avec "46 7th St. Johns Park", "St." est consommé trop tôt, le type de rue est incorrectement assigné à 'Park' et le stae de 'CA' devient la banlieue.

2 Smith St Suburb NJ 12345    2 Smith   St Suburb   NJ 12345 
25 MIRROR LAKE DR LITTLE EGG HARBOR 25 MIRROR LAKE DR Hbr NJ      0 
74B Old Bohema Rd N, St. Johns Park 74 B Old Bohema Rd St Johns Park CA 95472 
74 Mt Baw Baw Rd Suite C Some Park C 74 Mt Baw Baw Rd S Park CA      0 
74 Old Bohema Rd Bldg A Some Park CA 74 Old Bohema Rd B Park CA      0 
74 Old Bohema Rd Rm 123A Some Park C 74 Old Bohema Rd R Park CA      0 
Lot 74 Old Bohema Rd Some Park CA 95 0 Old Bohema Rd S Park CA      0 
22 Glen Alpine Way Some Park CA 9547 22 Glen Alpine Way Park CA      0 
4/6 Bohema Rd, St. Johns Park CA 954 4 6 Bohema  Rd St Johns Park CA 95472 
46 The Parade, St. Johns Park CA 954 46 The     Parade     0 
46 7th St. Johns Park CA 95472   46 7th St Johns Park CA      0 
46 B Avenue Johns Park CA 95472  46 B Avenue Johns Park CA      0 
46 Avenue C Johns Park CA 95472  46 Avenue C Johns Park CA      0 
46 Broadway Johns Park CA 95472  46 Broadway Johns Park CA      0 
46 State Route 19 Johns Park CA 9547 46 State Route 19 Park CA      0 
46 John F Kennedy Drive Johns Park C 46 John F Kennedy Park CA      0 
PO Box 213 Somewhere IO 1234   0 Somewhere   IO      0 
1 BEACH DR SE # 2410 ST PETERSBURG F 1 BEACH DR SE # 2 St PETERSBURG  FL 33701 
# 123 12 BEACH DR SE ST PETERSBURG F 12 BEACH DR SE  St PETERSBURG  FL 33701 
46 Broad Street #12 Suburb CA 95472 46 Broad   St       0 

J'ai développé un module Perl qui permet d'identifier un grand nombre de ces modèles plus difficiles https://metacpan.org/release/Lingua-EN-AddressParse. Il reconnaît les expressions idiomatiques telles que «The Parade», nth Street, les adresses de propriétés secondaires telles que «46 Broad Street # 12» et bien d'autres encore