Ссылка на регулярное выражение в 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
Другие вопросы по тегам