Я пытаюсь создать регулярное выражение для анализа данных ниже, но не могу получить второй совпадающий шаблон 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:
Итак, у name
один IP и одно имя, у names
есть список пар?
Как вы это разбираете? Пожалуйста, отредактируйте свой вопрос и включите код Perl вокруг вашего соответствия.
да, в основном я хочу IP, пары имен в моем Perl-скрипте.
@simbabque, я обновил вопрос фрагментом кода perl и скриншотом регулярного выражения 101, может быть, это поможет. Спасибо
Если может быть произвольное количество повторений, вероятно, лучше извлечь токены, а затем перебрать их, используя очень простое регулярное выражение.
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 }
}
1.1.1.1 testIp1 2.2.2.2 testIp2 192.168.1.1 testIp3