【问题标题】:Regex capture not returning expected array正则表达式捕获不返回预期的数组
【发布时间】:2019-08-14 18:38:21
【问题描述】:

我正在尝试使用正则表达式生成一组捕获组,但捕获组没有捕获我期望的字符串。

我的输入类似于以下一般格式:

S2244060800027008209302B000A667A6201A6828E1976007A000A52820009A3420009B0FE1F

此字符串包含以下组件: 一个 4 个字符的前缀,3 个字节的地址,一系列 2 个字节的数据块,一个 1 个字节的行终止符。

我只关心地址和数据块。

我尝试使用的正则表达式是: /\w{4}(\w{6})(\w{4})+/;

(在执行正则表达式之前,我有一个使用子字符串解析输入的不优雅的解决方案,但我讨厌它......)

原来的非功能代码如下:

open IN, "<$ARGV[0]" or die "Could not open '$ARGV[0]': $!\n";
open OUT, ">$ARGV[0].txt" or die "Could not open '$ARGV[0].txt': $!\n";

while (<IN>)
{
    print OUT join(" ",/^\w{4}(\w{6})(\w{4})+/)."\n"; 
}
close IN;
close OUT;

我想要的输出是一个包含以下元素的数组:

@array = [406080, 0027, 0082, 0930, 2B00, 0A66, 7A62, 01A6, 828E, 1976, 007A, 000A, 5282, 0009, A342, 0009, B0FE]

但是前面的正则表达式导致一个两元素数组只包含 3 字节地址和最后一个数据块:

@array = [406080, B0FE]

这对我来说意味着我对正则表达式捕获组的工作方式有一个基本的误解,我想澄清一下。

为了完整起见,这是我糟糕的解决方法:

    open IN, "<$ARGV[0]" or die "Could not open '$ARGV[0]': $!\n";    
    open OUT, ">$ARGV[0].txt" or die "Could not open '$ARGV[0].txt': $!\n";

    while (<IN>)
    {
        print OUT substr($_, 4, 6)." ".join(" ",substr($_, 10) =~ /\w{4}/g)."\n"; 
    }

    close IN;
    close OUT;

【问题讨论】:

  • S224 会发生什么?
  • 它作为非捕获匹配被丢弃,
  • 我不认为正则表达式是正确的工具

标签: regex perl regex-group regex-greedy


【解决方案1】:

量化一个捕获组不会创建多个捕获组。它根据量词进行匹配,但只捕获最后一个匹配项。

unpack更适合提取部分二进制数据:

#!/usr/bin/perl
use warnings;
use strict;

my $s = 'S2244060800027008209302B000A667A6201A6828E1976007A000A52820009A3420009B0FE1F';

my $exp = [qw[ 406080 0027 0082 0930 2B00 0A66 7A62 01A6 828E 1976 007A 000A 5282 0009 A342 0009 B0FE ]];

my @result = unpack 'x4A6(A4)*', $s;
die unless '1F' eq pop @result;

use Test::More tests => 1;
is_deeply \@result, $exp;

【讨论】:

  • 感谢您的回复。你能为我澄清一些关于 unpack 的细节吗?在模板中购买你的第一组括号是什么?为什么最后一个字节似乎与模板不匹配而被捕获?
  • 对不起,括号不是必需的,它们是我实验的结果。已删除。
猜你喜欢
  • 2018-03-29
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多