Perl - если условие для регулярных выражений захваченных групп - PullRequest
1 голос
/ 27 сентября 2019

У меня есть файл журнала и регулярное выражение, которое соответствует каждой строке файла журнала и захватывает группы.Я хочу напечатать только те строки журнала, которые имеют status = 404.

Вот что я пытался сделать:

perl -ne '/(?<remote_addr>[-.\d]+) - (?<remote_user>[-.\d]+) \[(?<time_local>.*)\] "(?<request>.*)" (?<status>\d+) (?<body_bytes_send>\d+) (?<request_length>\d+) "(?<http_referer>.*)" "(?<http_user_agent>.*)" "(?<http_accept_encoding>.*)" "(?<http_x_forwarded_for>.*)" "(?<request_time>.*)" "(?<upstream_response_time>.*)" "(?<host>.*)"/  &&  print "$1\t$2\t$3\t$4\t$5\t$6\t$7\t$8\t$9\t$10\t$11\t$12\t$13\t$14\n" if ($5 == 404)' nginx.log > output/temp.log

Но, похоже, это ничего не печатает.

Моя строка журнала выглядит так:

100.300.500.900 - - [23/Sep/2019:23:59:56 +0000] "POST /some/address HTTP/1.1" 200 1024 666 "-" "Mozilla/5.0 (Windows_NT ia32) node.js/4.4.0 v8/4.5.103.35" "-" "200.400.800.160" "10.30" "90.270" "www.mygoodserver.com"

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

Кто-нибудь может помочь?Я новичок в Perl.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2019

Ваш код имеет форму

/regex/ && print "some string\n" if ($5 == 404);

Это эквивалентно

if ($5 == 404) {
    /regex/ && print "some string\n";
}

Другими словами, ваш код пытается использовать $5 перед запуском регулярного выражения, которое его устанавливает.

Чтобы исправить логику, вам нужно использовать

if (/regex/ && $5 == 404) {
    print "some string\n";
}

Или в одной строке:

print "some string\n" if /regex/ && $5 == 404;

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

/(?<remote_addr>[-.\d]+) - (?<remote_user>[-.\d]+) \[(?<time_local>.*)\] "(?<request>.*)" <strong><em>(?<status>404)</em></strong> (?<body_bytes_send>\d+) (?<request_length>\d+) "(?<http_referer>.*)" "(?<http_user_agent>.*)" "(?<http_accept_encoding>.*)" "(?<http_x_forwarded_for>.*)" "(?<request_time>.*)" "(?<upstream_response_time>.*)" "(?<host>.*)"/

Тогда вам не нужна отдельная проверка.

1 голос
/ 27 сентября 2019

Версия модификатора оператора if записывается после команды, но оценивается перед ней.Таким образом, $ 5 не имеет значения при сравнении с 404. Включите совпадение в условие, чтобы оно произошло в нужное время:

print "...\n" if /.../ && $5 == 404;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...