Ссылка на регулярное выражение в Perl не жадная
Это рабочее регулярное выражение:
/(ANSI|AAMVA) (\d{6})(\d{2})(\d{2})(\d{0,2})((?:DL)|(?:ID))+(.*?)\g{-2}+([^"]+)/
Это пример строки:
"@\n\nANSI 6334290212DL00389199ZO04420478DLDAQ3572928\nDAASMITH, JOHN DOE\nDAG\nDAL4389 NE 47TH AVE\nDAIASHLAND\nDAJOR\nDAK97555 \nDARC \nDASD \nDATM \nDAU504\nDAW180\nDBA12201212\nDBB19780303\n"
Я пытаюсь сопоставить разделитель, либо DL
или же ID
это может быть в строке во второй раз.
Я хочу соответствовать тому, что DL
или же ID
соответствует ранее.
Проблема в том, если я использую ?
для этого он перестает быть жадным и предпочитает 0 матчей.
Я в тупике, я что-то упускаю из виду ?
работает?
Редактировать: проблема не в извлечении данных JSON, а в синтаксическом анализе бита msg, использование JSON ничего не делает для этого. Я обрезал струну как раз к соответствующей части.
Исправление @hobbs работает, потому что оно позволяет мне изменить ?
к +
и все равно ничего не соответствует, если ничего не существует.
Работает!:)
/(ANSI|AAMVA) (\d{6})(\d{2})(\d{2})(\d{0,2})((?:DL)|(?:ID))+(.*?)(?:\g{-2}|(?="))+([^"]+)/
2 ответа
Проблема не в том \g{-2}?
не жадный, это то, что (.*?)
непосредственно перед тем, как это не жадный, и \g{-2}?
не способен ничего соответствовать, а это значит, что он не может потерпеть неудачу. И если он не может потерпеть неудачу, то он не вынуждает группу перед этим соответствовать больше чем 0 символов. Так неизменно, (.*?)
ничего не будет соответствовать, \g{-2}
ничего не будет соответствовать, и ([^"]+)
будет соответствовать всему.
Я не совсем понимаю формат, который вы пытаетесь извлечь (кроме того, что он старый и странный и напоминает мне о записях счетов CIBER), но я бы посоветовал вам либо больше привязки, чтобы сосредоточить внимание вашего регулярного выражения на нужном месте или вам нужно обновить что-то вроде правильного парсера для формата. Так как вы говорите, что вы добавили ?
чтобы справиться со случаем, когда разделитель никогда не появляется, самое быстрое исправление бинтов может быть (?:\g{-2}|(?="))
который утверждает, что вы либо нашли разделитель, либо попали в заключительную цитату, не найдя его.
Хотя наблюдение Бородина также верно; было бы намного лучше сначала декодировать JSON, а затем работать со строкой из декодированной структуры JSON, вместо того, чтобы пытаться выполнить регулярное выражение непосредственно в JSON. В этом случае вы должны искать \z
(конец строки), а не "
,
Ваши данные в формате JSON, и очень неправильно пытаться обрабатывать их с помощью шаблонов регулярных выражений. Есть совершенно хорошие Perl-модули для преобразования текста в структуру данных с возможностью навигации
Я не могу точно понять, что вам нужно, потому что вы говорите о DA
а также ID
струны и ID
не встречается нигде в ваших данных образца. Но эта короткая программа должна помочь
use strict;
use warnings 'all';
use feature 'say';
use JSON 'decode_json';
my $json = do {
local $/;
<DATA>;
};
my $data = decode_json $json;
say $data->{msg};
__DATA__
{"name":"SC","hostname":"tukwila","pid":11,"level":30,"msg":"@\n\nANSI 6334290212DL00389199ZO04420478DLDAQ3572928\nDAASMITH, JOHN DOE\nDAG\nDAL4389 NE 47TH AVE\nDAIASHLAND\nDAJOR\nDAK97555 \nDARC \nDASD \nDATM \nDAU504\nDAW180\nDBA12201212\nDBB19780303\n","time":"2016-04-02T01:09:07.113Z","v":0}
выход
@
ANSI 6334290212DL00389199ZO04420478DLDAQ3572928
DAASMITH, JOHN DOE
DAG
DAL4389 NE 47TH AVE
DAIASHLAND
DAJOR
DAK97555
DARC
DASD
DATM
DAU504
DAW180
DBA12201212
DBB19780303