Как создать регулярное выражение, не способное получить вторую группу шаблона соответствия

Я пытаюсь создать регулярное выражение для анализа данных ниже, но не могу получить второй совпадающий шаблон 2.2.2.2 testIp2. Поскольку у вас нет большого воздействия на регулярное выражение.

Данные для анализа:

show names
names 1.1.1.1 testIp1 2.2.2.2 testIp2
name 192.168.1.1 testIp3
umesh 192.168.1.2 testIp4

Регулярное выражение, которое я мог бы создать:

^(?:name|names)(?:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\S+))

Вот мой фрагмент кода на Perl:

while( $data =~ /^(?:name|names)(?:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\S+))/mg) {
    $LOGGER->debug("IPs : $1 : $2");
}

На снимке экрана ниже проверьте, что ip 2.2.2.2 testIP2 не соответствует инструменту regex101:

1.1.1.1 testIp1 2.2.2.2 testIp2 192.168.1.1 testIp3

umesh 03.02.2023 12:54

Итак, у name один IP и одно имя, у names есть список пар?

simbabque 03.02.2023 12:54

Как вы это разбираете? Пожалуйста, отредактируйте свой вопрос и включите код Perl вокруг вашего соответствия.

simbabque 03.02.2023 12:55

да, в основном я хочу IP, пары имен в моем Perl-скрипте.

umesh 03.02.2023 12:55

@simbabque, я обновил вопрос фрагментом кода perl и скриншотом регулярного выражения 101, может быть, это поможет. Спасибо

umesh 03.02.2023 13:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
92
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

if ($data =~ /^names?(?:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\S+))/) {
    my $match = $1;
    while (s/$match/^(\d{1,3}(\.\d{1,3}){3})\s+/) {
      $LOGGER->debug("IPs : $1 : $2");
    }
}

Думаю, я бы просто разобрал это. Внутри регулярного выражения вы можете иметь код в (?{...}) структурах. Переменная $^N — это последний захваченный вами текст, а $^R — результат последнего (?{...}). Это немного сбивает с толку, и, возможно, вы не хотите никому этого желать, но это очень мощно (и я трачу на это большую часть первой главы Mastering Perl):

$_ = <<~'HERE';
    show names
    names 1.1.1.1 testIp1 2.2.2.2 testIp2
    name 192.168.1.1 testIp3
    umesh 192.168.1.2 testIp4
    HERE

my @found;

() = / # list context to get all the matches with /g
    ^
    names?
    (
        \h+
        ([0-9.]+)(?{ $^N })
        \h+
        (\w+)(?{ push @found, [ $^R, $^N ] })
    )+
    /gxm;

use Data::Dumper;
say Dumper( \@found );

Это может иметь больше смысла, если вы видите, что $^N назначено временным переменным (хотя вам нужно объявить их вне регулярного выражения):

() = / # list context to get all the matches with /g
    ^
    names?
    (
        \h+
        ([0-9.]+)(?{ $ip = $^N })
        \h+
        (\w+)(?{ $name = $^N; push @found, [ $ip, $name ] })
    )+
    /gxm;

Вот результат. Я создал кортежи, но вы можете обрабатывать их любым удобным для вас способом:

$VAR1 = [
          [
            '1.1.1.1',
            'testIp1'
          ],
          [
            '2.2.2.2',
            'testIp2'
          ],
          [
            '192.168.1.1',
            'testIp3'
          ]
        ];

Однако немного расстраивает, что в Perl это не проще. Я бы предпочел иметь что-то вроде этого, где это ближе к парсеру. %- не запоминает все помеченные совпадения в (...)+, а только последнее.

while(1) {
    if ( /\Gshow names\R/gc ) {
        say "Found start";
        }
    elsif ( /\Gname (?<ip>\S+) (?<name>\S+)\R/gc ) {
        ...
        next;
        }
    elsif ( /\Gnames (?:(?<ip>\S+) (?<name>\S+)\h*)+\R/gc ) {
        ... something with %-, but that doesn't work ...
        next;
        }
    else { last }
    }

Другие вопросы по теме