perl 正则表达式太贪心了
perl regex too greedy
我经历了其他成员提出的类似问题,并应用(或尝试应用)他们询问的解决方案,但他们没有解决我的问题。我的模式匹配和分组太贪心了,不会在第一个管道 (|) 处停止。如果我说得更具体一些,我认为可以,但我想弄清楚如何在管道的第一个实例中停止模式匹配?
这里有几行
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 脚本 return 上述数据的以下输出:
09:30:00.063|13:30:00.050|ABZ5702
09:37:21.208|13:37:21.206|136404
我尝试了所有这些和其他几个版本,但无法生成上述输出:
#$msg =~ s/([^|]*).*|52=([^|]*).*|11=([^|]*).*/||/;
$msg =~ s/(.+)\|??.*|52=([^|]*).*|11=([^|]*).*/||/;
#$msg =~ s/^([^|]*).??|52=([^|]*).??|11=([^|]*).*/||/;
#$msg =~ s/^([^\|??]*).*|52=([^\|??]*).*|11=([^\|??]*).*/||/;
#$msg =~ s/(.*\|??).*|52=(.+\|??).*|11=(.+\|??).*/one |two |three /;
#$msg =~ s/(.*?|).*|52=(.*?|).*|11=(.*|?).*/||/;
#$msg =~ /(.*)|??.*|52=(.*)|??.*|11=(.*)|??.*/||/;
#$msg =~ s/|.*-[0-3][0-9]:/|/;
print "$msg\n";```
我知道给猫剥皮的方法不止一种,但在某些情况下我需要使用模式匹配方法。我怎样才能使用模式匹配在第一个管道 (|) 停止每个组的地方生成预期的输出?有人可以告诉我我做错了什么吗?
试试这个:
s/(.*?)\|.*\|52=([^|]*).*\|11=([^|]*).*/ /;
有几个竖线分隔符需要转义。
你需要看看非贪婪匹配https://docstore.mik.ua/orelly/perl/cookbook/ch06_16.htm
第一个匹配组是(.*?)
而不是(.*)
。 ?
表示我们匹配的越少越好。
一般来说,在perl中解析FIX,只要没有重复组,我建议先在|
上拆分,然后创建标签值对的散列。
我会做一些不同的事情 - 将行拆分为数组并处理数组的单个元素。
如果行的格式预先确定并且永远不会改变,则正则表达式可能是一种特定情况下可接受的解决方案。
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
我经历了其他成员提出的类似问题,并应用(或尝试应用)他们询问的解决方案,但他们没有解决我的问题。我的模式匹配和分组太贪心了,不会在第一个管道 (|) 处停止。如果我说得更具体一些,我认为可以,但我想弄清楚如何在管道的第一个实例中停止模式匹配?
这里有几行
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 脚本 return 上述数据的以下输出:
09:30:00.063|13:30:00.050|ABZ5702
09:37:21.208|13:37:21.206|136404
我尝试了所有这些和其他几个版本,但无法生成上述输出:
#$msg =~ s/([^|]*).*|52=([^|]*).*|11=([^|]*).*/||/;
$msg =~ s/(.+)\|??.*|52=([^|]*).*|11=([^|]*).*/||/;
#$msg =~ s/^([^|]*).??|52=([^|]*).??|11=([^|]*).*/||/;
#$msg =~ s/^([^\|??]*).*|52=([^\|??]*).*|11=([^\|??]*).*/||/;
#$msg =~ s/(.*\|??).*|52=(.+\|??).*|11=(.+\|??).*/one |two |three /;
#$msg =~ s/(.*?|).*|52=(.*?|).*|11=(.*|?).*/||/;
#$msg =~ /(.*)|??.*|52=(.*)|??.*|11=(.*)|??.*/||/;
#$msg =~ s/|.*-[0-3][0-9]:/|/;
print "$msg\n";```
我知道给猫剥皮的方法不止一种,但在某些情况下我需要使用模式匹配方法。我怎样才能使用模式匹配在第一个管道 (|) 停止每个组的地方生成预期的输出?有人可以告诉我我做错了什么吗?
试试这个:
s/(.*?)\|.*\|52=([^|]*).*\|11=([^|]*).*/ /;
有几个竖线分隔符需要转义。
你需要看看非贪婪匹配https://docstore.mik.ua/orelly/perl/cookbook/ch06_16.htm
第一个匹配组是(.*?)
而不是(.*)
。 ?
表示我们匹配的越少越好。
一般来说,在perl中解析FIX,只要没有重复组,我建议先在|
上拆分,然后创建标签值对的散列。
我会做一些不同的事情 - 将行拆分为数组并处理数组的单个元素。
如果行的格式预先确定并且永远不会改变,则正则表达式可能是一种特定情况下可接受的解决方案。
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