0

我有一些要在 Perl 中解析的数据,并且在不久的将来会添加越来越多不同格式的数据。我想做的是编写一个易于使用的函数,我可以将字符串和正则表达式传递给它,它会返回括号中的任何内容。它会像这样工作(伪代码):

sub parse {
  $data = shift;
  $regex = shift;

  $data =~ eval ("m/$regex/")
  foreach $x ($1...$n)
  {
    push (@ra, $x); 
  }
  return \@ra;
}

然后,我可以这样称呼它:

@subs = parse ($data, '^"([0-9]+)",([^:]*):(\W+):([A-Z]{3}[0-9]{5}),ID=([0-9]+)');

如您所见,此代码存在一些问题。我不知道 eval 是否有效,'foreach' 肯定无效,而且不知道有多少括号,我不知道循环多少次。

这对于拆分来说太复杂了,所以如果我忽略了另一个功能或可能性,请告诉我。

谢谢你的帮助!

4

4 回答 4

6

在列表上下文中,正则表达式将返回所有带括号的匹配项的列表。

所以你所要做的就是:

my @matches = $string =~ /regex (with) (parens)/;

并假设它匹配,@matches将是两个捕获组的数组。

所以使用你的正则表达式:

my @subs = $data =~ /^"([0-9]+)",([^:]*):(\W+):([A-Z]{3}[0-9]{5}),ID=([0-9]+)/;

此外,当你有很长的正则表达式时,Perl 有x修饰符,它位于结束正则表达式分隔符之后。修饰符允许您在x正则表达式中放置空格和换行符以提高可读性。

如果您担心捕获组的长度可能为零,您可以传递匹配@subs = grep {length} @subs项以将它们过滤掉。

于 2010-06-17T22:37:25.300 回答
1

然后,我可以这样称呼它:

@subs = parse($data, 
          '^"([0-9]+)",([^:]*):(\W+):([A-Z]{3}[0-9]{5}),ID=([0-9]+)');

相反,将其称为:

parse($data, 
    qr/^"([0-9]+)",([^:]*):(\W+):([A-Z]{3}[0-9]{5}),ID=([0-9]+)/);

此外,如果您可以使用命名捕获(即 Perl 5.10 和更高版本),您的任务会变得更简单。这是一个例子:

#!/usr/bin/perl

use strict; use warnings;

my %re = (
    id => '(?<id> [0-9]+ )',
    name => '(?<name> \w+ )',
    value => '(?<value> [0-9]+ )',
);

my @this = (
    '123,one:12',
    '456,two:21',
);

my @that = (
    'one:[12],123',
    'two:[21],456',
);

my $this_re = qr/$re{id}   ,   $re{name}    : $re{value}/x;
my $that_re = qr/$re{name} : \[$re{value}\] , $re{id}   /x;

use YAML;

for my $d ( @this ) {
    print Dump [ parse($d, $this_re) ];
}

for my $d ( @that ) {
    print Dump [ parse($d, $that_re) ];
}

sub parse {
    my ($d, $re) = @_;
    return unless $d =~ $re;
    return my @result = @+{qw(id name value)};
}

输出:

---
- 123
- 一
- 12
---
- 456
- 二
- 21
---
- 123
- 一
- 12
---
- 456
- 二
- 21
于 2010-06-18T14:58:22.077 回答
0

您正在尝试使用正则表达式解析复杂的表达式 - 这对于这项工作来说是一个不足的工具。回想一下,正则表达式不能解析高级语法。直觉上,任何可能嵌套的表达式都不能用正则表达式解析。

于 2010-06-17T22:36:57.933 回答
0

当您想在括号对中查找文本时,您需要使用Text::Balanced

但是,这不是你想要做的,所以它不会帮助你。

于 2010-06-17T22:58:57.943 回答