Разобрать адрес с регулярным выражением - PullRequest
1 голос
/ 18 февраля 2010

Мне нужно создать цикл, и с помощью регулярного выражения заполнить любую из 4 переменных

$address, $street, $town, $lot

В цикл будет передана строка, в которой может содержаться информация, например, строки ниже

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

, так как что-либо после запятой это $town Я думал

(.*), (.*)

, тогда первый захват можно проверить с помощью (Lot \d*) (.*), (.*), если первый захват начинается с числа, то егоадрес (если слово с пробелом это $street), если одно слово, это просто $town

Ответы [ 5 ]

7 голосов
/ 18 февраля 2010

Посмотрите на Geo :: StreetAddress :: US , если это адреса США.

Даже если это не так, источник этого модуля должен дать вам представление о том, что происходит при разборе уличных адресов в свободной форме.

Вот скрипт, который обрабатывает отправленные вами адреса ( обновлено , более ранняя версия объединяет лот и номер в одну строку):

#!/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

Выход:

$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 голосов
/ 18 февраля 2010

Я бы посоветовал вам не пытаться делать все это в одном регулярном выражении, так как будет трудно проверить его правильность.

Сначала я бы разделил запятую.Все, что идет после запятой, это $ town, а если запятой нет, вся строка - это $ town.

Тогда я бы проверил, есть ли какая-либо информация о партии, и извлек ее из строки.

Тогда я буду искать номер и название улицы / проспекта.

Разделяй и властвуй :)

1 голос
/ 18 февраля 2010

Это должно разделиться на 3 части - как вы различаете адрес / улицу?

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

вот разбивка для ваших примеров

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

Если я правильно понимаю, этоодин адрес / улицу тоже отделяется

(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 голосов
/ 04 марта 2015

Geo :: StreetAddress :: US подходит для простых адресов, но в более сложных примерах может потерять контекст. Он будет анализировать названия улиц, пока не найдет пригород. Так с «46 7-й Сент-Джонс-Парк», «St. используется слишком рано, тип улицы неправильно присваивается «Парку», а уровень «CA» становится пригородом.

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

Я разработал модуль Perl, который может идентифицировать многие из этих более сложных шаблонов https://metacpan.org/release/Lingua-EN-AddressParse. Он распознает такие идиомы, как «Парад», n-я улица, адреса подвойств, такие как «46 Broad Street # 12» и многие другие.

0 голосов
/ 18 февраля 2010

Я не могу сопоставить последний, но для первых 3 вы можете использовать что-то вроде этого:

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

это регулярное выражение тестирования:

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

Вы можете использовать это в regexbuddy для проверки: ссылка

...