代码之家  ›  专栏  ›  技术社区  ›  Mark Biek

如何使这个正则表达式更紧凑?

  •  1
  • Mark Biek  · 技术社区  · 17 年前

    Small   0.0..20.0   0.00    1.49    25.71   41.05   12.31   0.00    80.56
    

    我想捕捉最后六个数字,忽略

    在本练习中,让我们忽略一个事实,即只进行某种字符串拆分而不是正则表达式可能更容易。

    ^(Small).*?[0-9.]+.*?[0-9.]+.*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+)
    

    有什么方法可以压缩它吗?

    3 回复  |  直到 17 年前
        1
  •  5
  •   Tim Pietzcker    17 年前

    如果您想将每个匹配项保留在单独的反向引用中,您别无选择,只能“拼出来”——如果您使用重复,您可以将所有六个组“作为一个”捕获,也可以仅捕获最后一个组,具体取决于捕获括号的位置。因此,不可能压缩正则表达式并保留所有六个单独的匹配项。

    ^Small\s+[0-9.]+\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)
    

    因为它显式地匹配空格。您的正则表达式将导致大量回溯。我的正则表达式在28步中匹配,你的正则表达式在106步中匹配。

    顺便说一句:在Python中,您可以简单地执行

    >>> pieces = "Small   0.0..20.0   0.00    1.49    25.71   41.05   12.31   0.00    80.56".split()[-6:]
    >>> print pieces
    ['1.49', '25.71', '41.05', '12.31', '0.00', '80.56']
    
        2
  •  3
  •   PhiLho    17 年前

    ^Small\s+(?:[\d.]+\s+){2}([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*$
    

        3
  •  1
  •   Kent Fredric    17 年前

    为了可用性,您应该使用字符串替换从复合部分构建正则表达式。

    $d = "[0-9.]+"; 
    $s = ".*?"; 
    
    $re = "^(Small)$s$d$s$d$s($d)$s($d)$s($d)$s($d)$s($d)$s($d)";
    

    如果您想获得真正的ANSI,您可以简短地使用元语法,使其更易于阅读:

    $re = "^(Small)_#D_#D_(#D)_(#D)_(#D)_(#D)_(#D)_(#D)"; 
    $re = str_replace('#D','[0-9.]+',$re); 
    $re = str_replace('_', '.*?' , $re ); 
    

    (通过这种方式,更改空间令牌或数字令牌的定义也变得非常简单)