代码之家  ›  专栏  ›  技术社区  ›  Matthew Simoneau Pär Wieslander

使用matlab正则表达式匹配重叠模式和捕获

  •  3
  • Matthew Simoneau Pär Wieslander  · 技术社区  · 15 年前

    我正在尝试分析如下所示的日志文件:

    %%%% 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
    

    问题是,由于第二个分隔符作为第一个匹配项的一部分使用,所以它只捕获其他每一个句点。

    在其他语言中,可以使用lookaround运算符(lookahead、lookback)来解决这个问题。这个 documentation on regular expressions 解释了这些如何在matlab中工作,但是我还没有能够在捕获匹配项的同时让它们工作。也就是说,我不仅需要能够匹配每个分隔符,还需要提取部分匹配(时间戳)。

    这有可能吗?

    另外,我意识到我可以通过编写一个简单的状态机来解决这个问题,或者通过在定界符和后处理上进行匹配来解决这个问题,如果没有办法的话。

    更新: 谢谢大家的变通方案。我从开发人员那里听说,目前没有办法用matlab中的正则表达式引擎来实现这一点。

    3 回复  |  直到 15 年前
        1
  •  2
  •   gnovice    15 年前

    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'
    
        2
  •  1
  •   Sundar R    15 年前

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

        3
  •  0
  •   Alan Moore Chris Ballance    15 年前

    您所要做的就是在与第二个时间戳匹配的regex的部分包装一个lookahead:

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

    编辑:此处没有命名组:

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