Perl Regex слишком жадный - PullRequest
       43

Perl Regex слишком жадный

0 голосов
/ 06 ноября 2019

Я прошел через аналогичные вопросы, заданные другими участниками, и применил (или попытался применить) решения из своего запроса, но они не помогли решить мою проблему. Мое сопоставление с образцом и группировка слишком жадные и не останавливаются на первой трубе (|). Если я получу более конкретную информацию, я думаю, что это возможно, но я пытаюсь выяснить, как я могу остановить сопоставление с образцом при первом экземпляре канала?

Вот пара строк

09:30:00.063|IN:|8=FIX.4.2|9=206|35=D|34=5159|49=CLIENT|52=20191024-13:30:00.050|56=SERV|57=DEST|1=05033|11=ABZ5702|15=USD|21=1|38=2000|40=2|44=92.48|47=A|54=5|55=RC|60=20191024-13:30:00.050|111=0|114=N|336=X|5700=AP|9281=SOV|10=202
09:37:21.208|IN:|8=FIX.4.2|9=170|35=D|34=5184|49=CLIENT|52=20191024-13:37:21.206|56=SERV|57=ATXB|1=J5129|11=136404|15=USD|21=1|38=100|40=2|44=1.39|47=A|54=2|55=DIW|59=2|60=20191024-13:30:00.206|10=029

Я ожидаю, что мой Perl-скрипт выдаст следующий вывод из приведенных выше данных:

09:30:00.063|13:30:00.050|ABZ5702
09:37:21.208|13:37:21.206|136404

Я попробовал все это и несколько других вариантов, но не смог получить его для вывода вышеупомянутого результата:

    #$msg =~ s/([^|]*).*|52=([^|]*).*|11=([^|]*).*/$1|$2|$3/;
    $msg =~ s/(.+)\|??.*|52=([^|]*).*|11=([^|]*).*/$1|$2|$3/;
    #$msg =~ s/^([^|]*).??|52=([^|]*).??|11=([^|]*).*/$1|$2|$3/;
    #$msg =~ s/^([^\|??]*).*|52=([^\|??]*).*|11=([^\|??]*).*/$1|$2|$3/;
    #$msg =~ s/(.*\|??).*|52=(.+\|??).*|11=(.+\|??).*/one $1|two $2|three $3/;
    #$msg =~ s/(.*?|).*|52=(.*?|).*|11=(.*|?).*/$1|$2|$3/;
    #$msg =~ /(.*)|??.*|52=(.*)|??.*|11=(.*)|??.*/$1|$2|$3/;
    #$msg =~ s/|.*-[0-3][0-9]:/|/;

print "$msg\n";```

Я понимаю, что есть и другие способы шкурки кошки, но есть случаи, когда мне нужно использовать подход сопоставления с образцом. Как я могу получить его для получения ожидаемого результата, используя сопоставление с образцом, где он останавливает каждую группу в первом канале (|)? Может кто-нибудь сказать мне, что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Я бы сделал это немного по-другому - разбить строку на массив и работать с отдельным элементом массива.

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

use strict;
use warnings;

use Data::Dumper;

my $debug = 0;

while( my $line = <DATA> ) {
    my @array = split /\|/, $line;

    print Dumper(\@array) if $debug;

    $array[7]  =~ s/.+?-//;
    $array[11] =~ s/\d+=//;

    printf "%s\n", join '|', @array[0,7,11];

}

__DATA__
09:30:00.063|IN:|8=FIX.4.2|9=206|35=D|34=5159|49=CLIENT|52=20191024-13:30:00.050|56=SERV|57=DEST|1=05033|11=ABZ5702|15=USD|21=1|38=2000|40=2|44=92.48|47=A|54=5|55=RC|60=20191024-13:30:00.050|111=0|114=N|336=X|5700=AP|9281=SOV|10=202
09:37:21.208|IN:|8=FIX.4.2|9=170|35=D|34=5184|49=CLIENT|52=20191024-13:37:21.206|56=SERV|57=ATXB|1=J5129|11=136404|15=USD|21=1|38=100|40=2|44=1.39|47=A|54=2|55=DIW|59=2|60=20191024-13:30:00.206|10=029
2 голосов
/ 06 ноября 2019

Попробуйте это: s/(.*?)\|.*\|52=([^|]*).*\|11=([^|]*).*/$1 $2 $3/;

Была пара трубчатых разделителей, которые нужно было экранировать.

Вам нужно посмотреть на не жадное совпадение https://docstore.mik.ua/orelly/perl/cookbook/ch06_16.htm

Первая подходящая группа - (.*?) вместо (.*). ? означает, что мы сопоставляем как можно меньше.

В общем, для разбора FIX в perl, если нет повторяющихся групп, я бы рекомендовал сначала разбить на |, а затем создать хешпар тег-значение.

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