Perl regex файл одной строки - PullRequest
2 голосов
/ 25 марта 2019

Я использую cat, чтобы получить содержимое файла, а затем я использую регулярное выражение, чтобы получить то, что я хочу.Когда я изменяю порядок if в примере, я ставлю ПАРОЛЬ в качестве второго, IP будет пустым.

#!/usr/bin/perl
my $param = $ARGV[0];

my $IP;
my $PASSWORD;
my $MODEM;
my @cat = `cat file`;

 foreach my $line (@cat){
    if ($line =~ /$param/){
        if ($line =~ /MODEM:(\w+)/g){ $MODEM = $1; }
        if ($line =~ /IP:((\d{1,3}\.){3}\d{1,3})/g){ $IP = $1; }
        if ($line =~ /PASSWORD:(.+)/g){ $PASSWORD = $1; }

        print $MODEM;
        print $IP;
        print $PASSWORD;

        }
}

Содержимое файла (данные изменяются на поддельные значения):

MODEM:SOMETHING ID:1000018 MAC:606060606060  ID2:123499  IP:1.1.1.1  PASSWORD:pass123

Ожидаемый результат:

SOMETHING1.1.1.1pass123 

Но когда я изменяю строку кода на это:

if ($line =~ /MODEM:(\w+)/g){ $MODEM = $1; }
if ($line =~ /PASSWORD:(.+)/g){ $PASSWORD = $1; }
if ($line =~ /IP:((\d{1,3}\.){3}\d{1,3})/g){ $IP = $1; }

результат будет:

SOMETHINGpass123 

т.е.IP пуст.Может кто-нибудь объяснить мне, почему это происходит?

Ответы [ 2 ]

7 голосов
/ 25 марта 2019

Возможно, это не тот ответ, который вы искали, но ИМХО для ваших структурированных данных возможен более простой подход, чем регулярное выражение:

  • разделение на пустое пространство для доступа к полям
  • каждоеполе имеет вид <KEY>:<VALUE, т. е. может быть преобразовано в хеш
#!/usr/bin/perl
use warnings;
use strict;

while (<DATA>) {
    chomp;
    my %fields = map { split(/:/) } split(' ');

    print "$fields{MODEM} $fields{IP} $fields{PASSWORD}\n"
}

exit 0;

__DATA__
MODEM:SOMETHING ID:1000018 MAC:606060606060  ID2:123499  IP:1.1.1.1  PASSWORD:pass123

Другая альтернатива будет

my %fields = /(\S+):(\S+)/g;

Тестовый прогон:

$ perl dummy.pl
SOMETHING 1.1.1.1 pass123
7 голосов
/ 25 марта 2019

Редактировать: вы, вероятно, не хотите использовать 3 сложных регулярных выражения для анализа вашего файла.См. Ответ Стефана Беккера для лучшего способа.

Вам необходимо удалить модификатор /g.

Последовательные совпадения с одной и той же строкой с /g, начиная с конца предыдущего совпадения.Взгляните на соответствующий абзац в perlretut .
В вашем файле сначала идет MODEM, затем IP, затем PASSWORD.Это означает, что после сопоставления /PASSWORD:(.+)/g вы не можете сопоставить /IP/g, который предшествует в вашей строке. Модификатор


/g в основном полезен, когда вы хотите сделать что-то вроде

while ($string =~ /.../g) { ... }

Или, конечно, в контексте списка, чтобы получить все совпадения:

 @matches = $string =~ /.../g

В вашем случае вы просто хотите получать разные совпадения один за другим, поэтому нет необходимости в /g модификатор.

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