R Regex для определения почтовых индексов Великобритании

Мой вопрос похож на this, но я ищу что-то R конкретное. У меня есть data.frame из десятков тысяч адресов, и мне нужно вытащить почтовые индексы. Почтовые индексы находятся в Великобритании и имеют формат {LETTER_LETTER_DIGIT LETTER_LETTER_DIGIT}. Аналогично следующему:

"8, Longbow Close, \ r \ nHarlescott Lane, \ r \ nShrewsbury, \ r \ nEngland, \ r \ nSY1 3GZ"

Я безрезультатно использовал варианты этого кода с stringr:

str_extract('^(\\[Gg]\\[Ii]\\[Rr] 0\\[Aa]{2})|(((\\[A-Za-z]\\[0-9]{1,2})|((\\ 
[A-Za-z]\\[A-Ha-hJ-Yj-y]\\[0-9]{1,2})|((\\[AZa-z]\\[0-9]\\[A-Za-z])|(\\[A-Za- 
z]\\[A-Ha-hJ-Yj-y]\\[0-9]?\\[A-Za-z]))))\\[0-9]\\[A-Za-z]{2})$',alfa$Address) 

person elliot    schedule 25.04.2018    source источник
comment
Почему безрезультатно? Что случилось? Полагаю, у вас нет совпадений из-за ^ и $. Удалите их или замените на \\b и используйте str_extract_all. И поменяйте местами аргументы, первый - ввод, второй - регулярное выражение. И не избегайте [, это начало класса символов.   -  person Wiktor Stribiżew    schedule 25.04.2018
comment
Почему у вас двойная обратная косая черта?   -  person Hugh    schedule 25.04.2018
comment
@ WiktorStribiżew, в первую очередь я получаю NA. После удаления ^ и $ и использования str_extract_all я получаю character(0).   -  person elliot    schedule 25.04.2018
comment
Потому что все [ совпадают как буквальные [. Уберите побеги. Почему вы изменили регулярное выражение в сообщении, на которое указали ссылку?   -  person Wiktor Stribiżew    schedule 25.04.2018


Ответы (2)


Якоря ^ и $ требуют, чтобы шаблон соответствовал всей строке. Вы можете обернуть шаблон \b(?:<pattern>)\b, чтобы эти коды соответствовали целым словам (\b - это граница слова). Кроме того, классы символов "испорчены", поскольку вы экранировали их [ начальную скобку (\[ соответствует буквальным [ символам). Кроме того, поменяйте местами аргументы: первый - ввод, второй - регулярное выражение. Кроме того, чтобы получить все совпадения, вам нужно использовать str_extract_all, а не str_extract.

Вы можете исправить код так:

library(stringr)
txt <- "8, Longbow Close,\r\nHarlescott Lane,\r\nShrewsbury,\r\nEngland,\r\nSY1 3GZ"
pattern <- "\\b(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\\s?[0-9][A-Za-z]{2}))\\b"
str_extract_all(txt, pattern)
# => [[1]]
#   [1] "SY1 3GZ"
person Wiktor Stribiżew    schedule 25.04.2018
comment
Спасибо за объяснение. Ваш код работает отлично! - person elliot; 25.04.2018

Вот более читаемый способ:

            if ($e{locate} =~ /\b([A-Z])([A-Z])([0-9])([A-Z]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5.$6.$7;
                    $e{zips} = $1.$2.$3.$4.' ' .$5.$6.$7;
            } elsif ($e{locate} =~ /\b([A-Z])([0-9])([A-Z]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5.$6;
                    $e{zips} = $1.$2.$3.' '.$4.$5.$6;
            } elsif ($e{locate} =~ /\b([A-Z])([0-9]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5;
                    $e{zips} = $1.$2.' '.$3.$4.$5;
            } elsif ($e{locate} =~ /\b([A-Z])([0-9])([0-9]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5.$6;
                    $e{zips} = $1.$2.$3.' '.$4.$5.$6;
            } elsif ($e{locate} =~ /\b([A-Z])([A-Z])([0-9]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5.$6;
                    $e{zips} = $1.$2.$3.' ' .$4.$5.$6;
            } elsif ($e{locate} =~ /\b([A-Z])([A-Z])([0-9])([0-9]) ([0-9])([A-Z])([A-Z])\b/) {
                    $e{zip} = $1.$2.$3.$4.$5.$6.$7;
                    $e{zips} = $1.$2.$3.$4.' '.$5.$6.$7;
            }
person Ervin Ruci    schedule 28.04.2018