使用MATLAB正则表达式将重叠模式与捕获匹配

时间:2009-05-11 15:53:55

标签: regex matlab

我正在尝试解析看起来像这样的日志文件:

%%%% 09-May-2009 04:10:29
% Starting foo
this is stuff
to ignore
%%%% 09-May-2009 04:10:50
% Starting bar
more stuff
to ignore
%%%% 09-May-2009 04:11:29
...

这段摘录包含两个我想提取的时间段,从第一个分隔符到第二个分隔符,从第二个分隔符到第二个分隔符。我想使用正则表达式来提取每个间隔的开始和停止时间。这主要有效:

p = '%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?%{4} (?<stop>.*?)\n';
times = regexp(c,p,'names');

返回:

times = 

1x16 struct array with fields:
    start
    name
    stop

问题是这只会捕获其他所有时段,因为第二个分隔符是第一次匹配的一部分。

在其他语言中,您可以使用环视操作符(lookahead,lookbehind)来解决此问题。 documentation on regular expressions解释了这些如何在MATLAB中工作,但是我仍然无法在捕获匹配时使这些工作正常。也就是说,我不仅需要能够匹配每个分隔符,而且还需要提取该匹配的一部分(时间戳)。

这可能吗?

P.S。我意识到我可以通过编写一个简单的状态机或通过匹配分隔符和后处理来解决这个问题,如果没有办法让它工作。

更新:感谢大家的解决方法。我从开发人员那里听说,目前没有办法用MATLAB中的正则表达式引擎。

3 个答案:

答案 0 :(得分:2)

MATLAB似乎无法将字符作为标记捕获而不从字符串中删除它们(或者,我应该说,无法使用MATLAB REGEXP)。但是,通过注意到一个文本块的停止时间等于下一个文本块的开始时间,我能够使用REGEXP捕获开始时间和名称,然后进行一些简单的处理以从中获取停止时间。开始时间。我使用了以下示例文本:

c =

%%%% 09-May-2009 04:10:29
% Starting foo
this is stuff
to ignore
%%%% 09-May-2009 04:10:50
% Starting bar
more stuff
to ignore
%%%% 09-May-2009 04:11:29
some more junk

...并应用以下表达式:

p = '%{4} (?<start>[^\n]*)\n% Starting (?<name>[^\n]*)[^%]*|%{4} (?<start>[^\n]*).*';

然后可以使用以下代码完成处理:

names = regexp(c,p,'names');
[names.stop] = deal(names(2:end).start,[]);
names = names(1:end-1);

...它为我们提供了上述示例文本的结果:

>> names(1)

ans = 

    start: '09-May-2009 04:10:29'
     name: 'foo'
     stop: '09-May-2009 04:10:50'

>> names(2)

ans = 

    start: '09-May-2009 04:10:50'
     name: 'bar'
     stop: '09-May-2009 04:11:29'

答案 1 :(得分:1)

如果您正在进行大量解析和此类工作,可以考虑使用Perl from within Matlab。它使您可以访问Perl强大的正则表达式引擎,并且还可以使许多其他问题更容易解决。

答案 2 :(得分:0)

您所要做的就是在正则表达式中与第二个时间戳匹配的前瞻部分:

'%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?(?=%{4} (?<stop>.*?)\n)'

编辑:这里没有命名组:

'%{4} (.*?)\n% Starting (.*?)\n.*?(?=%{4} (.*?)\n)'