Perl регулярное выражение исключает необязательное слово из соответствия - PullRequest
4 голосов
/ 26 марта 2020

У меня есть строки, и мне нужно извлечь из них только номера / цифры.

icnnumber:9876AB54321_IN
number:987654321FR
icnnumber:987654321YQ

Мне нужно извлечь данные из примера выше.

9876AB54321
987654321FR
987654321YQ

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

(icnnumber|number):(\w+)(?:_IN)

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

Ответы [ 6 ]

4 голосов
/ 26 марта 2020

Другой вариант получения только значений в качестве совпадения с помощью \K для сброса буфера совпадений

\b(?:icn)?number:\K[^\W_]+

Regex demo | Perl демо

Например

my $str = 'icnnumber:9876AB54321_IN
number:987654321FR
icnnumber:987654321YQ';

while($str =~ /\b(?:icn)?number:\K[^\W_]+/g ) {
  print $& . "\n";
}

Выход

9876AB54321
987654321FR
987654321YQ
4 голосов
/ 26 марта 2020

Если ваши извлекаемые строки имеют только верхний регистр и цифры c, зачем использовать \w, если это также соответствует _?

Как насчет совпадения:

#!/usr/bin/env perl

use strict;
use warnings;

while (<DATA>) {
   m/number:([A-Z0-9]+)/;
   print "$1\n";
}

__DATA__
icnnumber:9876AB54321_IN
number:987654321FR
icnnumber:987654321YQ
3 голосов
/ 26 марта 2020

Вы можете заменить \w (который соответствует буквам, цифрам и символам подчеркивания) на [^\W_], который почти такой же, но не соответствует символу подчеркивания:

(icnnumber|number):([^\W_]+)

См. Демонстрационную версию regex .

Если вы хотите убедиться, что icnnumber и number соответствуют целым словам, вы можете добавить границу слова в начале:

\b(icnnumber|number):([^\W_]+)
^^

Вы можете даже немного изменить структуру шаблона, чтобы не повторять number с использованием необязательной группы без захвата, см. ниже:

\b((?:icn)?number):([^\W_]+)
   ^^^^^^^^

Детали шаблона

  • \b - граница слова (сразу справа, должно быть начало строки или символа, отличного от буквы, di git или _)
  • ((?:icn)?number) - Группа 1: an необязательная последовательность icn подстроки, а затем number подстрока
  • : - : char
  • ([^\W_]+) - Группа 2: одна или несколько букв или цифр.
2 голосов
/ 26 марта 2020

Может быть, просто другое предложение, но , если ваши строки всегда действительны, вы можете просто разделить класс символов и извлечь второй индекс из полученного массива:

my $string= "number:987654321FR";
my @part = (split /[:_]/, $string)[1];
print @part

Или для всего массива строк:

@Array = ("icnnumber:9876AB54321_IN", "number:987654321FR", "icnnumber:987654321YQ");

foreach (@Array)
{
    my $el = (split /[:_]/, $_)[1];
    print "$el\n"
}

Результат:

9876AB54321
987654321FR
987654321YQ
1 голос
/ 26 марта 2020

Уже вы получили лучшие и лучшие ответы здесь, так или иначе, я пытаюсь решить ваш вопрос прямо сейчас.

Получить всю строку,

my $str = do { local $/; <DATA> }; #print $str;

Вы можете проверить первый метод группировки до _ или \b из строки ниже,

@arrs = ($str=~m/number\:((?:(?!\_).)*)(?:\b|\_)/ig);

(или)

Вы можете проверить не слова \W и _ для первой группировки здесь и нажатия совпадений в массиве

@arrs = ($str=~m/number\:([^\W\_]+)(?:\_|\b)/ig);

вывод на печать

print join "\n", @arrs;

__DATA__
icnnumber:9876AB54321_IN
number:987654321FR
icnnumber:987654321YQ
1 голос
/ 26 марта 2020

Регулярное выражение может иметь 'icn' в качестве опции, и часть интереса составляет 11 символов после :.

my $re = qr/(icn)?number:(.{11})/;

Фрагмент кода теста

use strict;
use warnings;
use feature 'say';

my $re = qr/(icn)?number:(.{11})/;

while(<DATA>) {
    say $2 if /$re/;
}

__DATA__
icnnumber:9876AB54321_IN
number:987654321FR
icnnumber:987654321YQ

Вывод

9876AB54321
987654321FR
987654321YQ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...