【问题标题】:Php Regex: how to match repeated patternsPhp Regex:如何匹配重复的模式
【发布时间】:2013-08-25 14:43:40
【问题描述】:

给出以下文字

bond0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
eth0: 11329920252 12554462    0    0    0     0          0      3561 13072970332 12899522    0    0    0     0       0          0

我需要捕获列值。我想到了这些行:

Regex: `(\w+):(?:\s+(\d+))+`
Php: `preg_match_all('/(\w+):(?:\s+(\d+))+/sim', $data, $regs)

但不幸的是,它只捕获第一列。

Array
(
    [0] => Array
        (
            [0] => dummy0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
            [1] => bond0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
            [2] => eth0: 11329920252 12554462    0    0    0     0          0      3561 13072970332 12899522    0    0    0     0       0          0
            [3] => ip6tnl0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
            [4] => lo: 51675995  100695    0    0    0     0          0         0 51675995  100695    0    0    0     0       0          0
            [5] => sit0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
            [6] => tunl0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
        )

    [1] => Array
        (
            [0] => 0
            [1] => 0
            [2] => 0
            [3] => 0
            [4] => 0
            [5] => 0
            [6] => 0
        )

)

有什么建议吗?谢谢 `

====编辑==== 明确一点:我知道我可以 preg_match 搜索 \d+ 值或将整个字符串分成几行并在每一行上运行explode,但我对正则表达式解决方案感兴趣,我将第一列作为第一个成员结果数组(实际上忘记在问题的初稿中放置捕获括号),以及带有数据的后续列,每一行都放在它的专用数组中......

【问题讨论】:

  • 在这里使用explode() 也是一个可行的解决方案。
  • $array = explode($var,"\t"); 会为你做的
  • 我不想使用explode,因为我在问题更新中写过的原因。无论如何谢谢。
  • 如果您没有找到preg_match 解决方案,我会在评论中添加我的解决方案:<?php $val = "bond0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 eth0: 11329920252 12554462 0 0 0 0 0 3561 13072970332 12899522 0 0 0 0 0 0"; $arr1 = explode("\n",$val); foreach ($arr1 as $key => $value) { $exp = explode(":",$value); $ex = preg_replace('/\s+/', ' ',trim($exp[1])); $arr[$exp[0]] = explode(" ",$ex); } var_dump($arr); ?>
  • 每行的列数是固定的吗?如果没有,您要求的是可变数量的捕获,并且只有 .NET 可以做到。

标签: php regex


【解决方案1】:

为什么要使用preg_matchpreg_match_all

$results = array();
foreach (preg_split("/\r\n|\r|\n/", $data) as $line)
{
    list($key, $values) = explode(":", $line);
    $results[$key] = preg_split("/\s/", trim($values));
}

只要每行不超过一个:,这应该可以工作。在我看来,这也是写这个的最短和最快的方法。

【讨论】:

  • 不是我想要的(而且似乎不可能这样做),但我将此答案标记为最优雅的。
【解决方案2】:

给你:

$data = explode("\n", $data);
$out = array();
foreach ($data as $d) {
    preg_match_all('/\s(\d+)/', $d, $matches);

使$matches[0] 等于匹配数组。然后你想将它添加到行数组中:

    $out[] = $matches[0];
}

您现在有一个锯齿状的行和列数组。所以,要参考第二行第四列,你可以去$out[1][3]

【讨论】:

  • 为什么要在空格周围加上括号?
  • 啊,不需要。已删除。
  • array_map( 'trim', $matches[0] ) 更好:)
  • 它更小,但性能会受到影响。 Foreach 更快,更灵活。
  • /\s(\d+)/,无需修剪即可获得相同的结果
【解决方案3】:

我知道您正在寻找preg_match 解决方案,但这是以防您找不到任何有用的答案

<?php
$val = "bond0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
eth0: 11329920252 12554462    0    0    0     0          0      3561 13072970332 12899522    0    0    0     0       0          0";
$arr1 = explode("\n",$val);
foreach ($arr1 as $value) {
    $exp = explode(":",$value);
    $ex = preg_replace('/\s+/', ' ',trim($exp[1]));
    $arr[$exp[0]] = explode(" ",$ex);
}
var_dump($arr);
?>

结果:

array (size=2)
  'bond0' => 
    array (size=17)
      0 => string '' (length=0)
      1 => string '0' (length=1)
      2 => string '0' (length=1)
      3 => string '0' (length=1)
      4 => string '0' (length=1)
      5 => string '0' (length=1)
      6 => string '0' (length=1)
      7 => string '0' (length=1)
      8 => string '0' (length=1)
      9 => string '0' (length=1)
      10 => string '0' (length=1)
      11 => string '0' (length=1)
      12 => string '0' (length=1)
      13 => string '0' (length=1)
      14 => string '0' (length=1)
      15 => string '0' (length=1)
      16 => string '0' (length=1)
  'eth0' => 
    array (size=17)
      0 => string '' (length=0)
      1 => string '11329920252' (length=11)
      2 => string '12554462' (length=8)
      3 => string '0' (length=1)
      4 => string '0' (length=1)
      5 => string '0' (length=1)
      6 => string '0' (length=1)
      7 => string '0' (length=1)
      8 => string '3561' (length=4)
      9 => string '13072970332' (length=11)
      10 => string '12899522' (length=8)
      11 => string '0' (length=1)
      12 => string '0' (length=1)
      13 => string '0' (length=1)
      14 => string '0' (length=1)
      15 => string '0' (length=1)
      16 => string '0' (length=1)

【讨论】:

    【解决方案4】:

    你可以这样做:

    $subject = <<<LOD
    dummy0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    bond0:  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    eth0: 11329920252 12554462 0 0 0 0 0 3561 13072970332 12899522 0 0 0 0 0 0
    ip6tnl0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    lo: 51675995 100695 0 0 0 0 0 0 51675995 100695 0 0 0 0 0 0
    sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    tunl0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    LOD;
    
    $pattern = '~^(?<item>\w+):|\G\h+(?<value>\d+)~m';
    preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
    $i=-1;
    foreach($matches as $match) {
        if (isset($match['value']))
            $result[$i]['values'][] = $match['value'];
        else {
            $i++;
            $result[$i]['item'] = $match['item']; }
    }
    print_r($result);
    

    您将获得您在 EDIT 中描述的格式。

    图案细节:

    ~               # pattern delimiter
    ^               # anchor for the line start (in multiline mode)
    (?<item>\w+)    # named capture "item"
    :       
    |               # OR
    \G              # force the match to be contigous from precedent
    \h+             #
    (?<value>\d+)   # named capture "value"
    ~m              # pattern delimiter, m modifier for multiline mode
    

    【讨论】:

    • 这是一种非常庞大的方法。
    • @ConnorPeet:不像你想象的那么“庞大”,因为该模式只适用一次。
    猜你喜欢
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多