如何用正则表达式分割字符串到2D数组


How to split string to 2D array with Regex?

我遇到了一个表面上看起来很简单的问题,但却击败了我微薄的正则表达式技能。我有一个字符串,我需要转换为数组,然后相应地处理值,这很简单,但是字符串的格式不能改变(它是在其他地方生成的),它的逻辑让我困惑。

字符串是:

[6] [2] [3] 12.00; [5] [4]

它基本上是一组id和十进制值(在本例中id 3 == 12.00)。id的数量可以随时改变,十进制值可以在任何一个或所有id中。

在理想情况下,我将拥有以下数组:

Array (
   [0] => Array (
             [id]  => 6
             [num] => 
          )
   [1] => Array (
             [id]  => 2
             [num] => 
          ) 
   [2] => Array (
             [id]  => 3
             [num] => 12.00 
          )
   Etc...

你们中的任何一个正则表达式巫师知道如何用比我更少的咒骂来完成这一点吗?

到目前为止,我已经能够提取id的使用:
preg_match_all('@'[(.*?)']@s', $string, $array);

和小数使用:

preg_match_all('/([0-9]+[,'.]{1}[0-9]{2})/', $string, $array);

示例:

<?php
$string = '[6] [2] [3] 12.00; [5] [4]';
preg_match_all('/'[(?P<id>'d+)'](?: (?P<num>['d'.]+);)?/', $string, $matches, PREG_SET_ORDER);
var_dump($matches);
输出:

array(5) {
  [0]=>
  array(3) {
    [0]=>
    string(3) "[6]"
    ["id"]=>
    string(1) "6"
    [1]=>
    string(1) "6"
  }
  [1]=>
  array(3) {
    [0]=>
    string(3) "[2]"
    ["id"]=>
    string(1) "2"
    [1]=>
    string(1) "2"
  }
  [2]=>
  array(5) {
    [0]=>
    string(10) "[3] 12.00;"
    ["id"]=>
    string(1) "3"
    [1]=>
    string(1) "3"
    ["num"]=>
    string(5) "12.00"
    [2]=>
    string(5) "12.00"
  }
  [3]=>
  array(3) {
    [0]=>
    string(3) "[5]"
    ["id"]=>
    string(1) "5"
    [1]=>
    string(1) "5"
  }
  [4]=>
  array(3) {
    [0]=>
    string(3) "[4]"
    ["id"]=>
    string(1) "4"
    [1]=>
    string(1) "4"
  }
}

如果您对id或NUMs列表感到满意,那么您可以将两个工作正则表达式合并为一个调用:

preg_match_all('@  '[(?P<id> 'd+ )]   |   (?P<num> ['d,.]+)  @xs',
         $string, $array, PREG_SET_ORDER);

如果您还使用PREG_SET_ORDER标志,这将为您提供一个关联数组列表,其中idnum设置。

像这样?我的php技能相当弱,所以你必须检查如何访问命名捕获组id/num

preg_match_all('/'[(?P<id>'d+)']'s*(?P<num>[-+]?'b[0-9]+(?:'.[0-9]+)?'b)?/', $subject, $result, PREG_SET_ORDER);
for ($matchi = 0; $matchi < count($result); $matchi++) {
    for ($backrefi = 0; $backrefi < count($result[$matchi]); $backrefi++) {
        # Matched text = $result[$matchi][$backrefi];
    } 
}

工作原理:

"
'[             # Match the character “[” literally
(?<id>         # Match the regular expression below and capture its match into backreference with name “id”
   'd             # Match a single digit 0..9
      +              # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
]              # Match the character “]” literally
's             # Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   *              # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
(?<num>        # Match the regular expression below and capture its match into backreference with name “num”
   [-+]           # Match a single character present in the list “-+”
      ?              # Between zero and one times, as many times as possible, giving back as needed (greedy)
   'b             # Assert position at a word boundary
   [0-9]          # Match a single character in the range between “0” and “9”
      +              # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
   (?:            # Match the regular expression below
      '.             # Match the character “.” literally
      [0-9]          # Match a single character in the range between “0” and “9”
         +              # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
   )?             # Between zero and one times, as many times as possible, giving back as needed (greedy)
   'b             # Assert position at a word boundary
)?             # Between zero and one times, as many times as possible, giving back as needed (greedy)
"

这不是正则表达式的方法,但也许它适合你:(当然它可以改进)

$str = "[6] [2] [3] 12.00; [5] [4]";
$str = str_replace(array('[',']'), '', $str);
$arr = explode(' ', $str);
$array = array();
for($i=0 ; $i < count($arr) ; $i++)
{   
    $isValue = strpos($arr[$i], '.');
    if($isValue !== false){
        continue;
    }   
    $key = $arr[$i];
    $ret = array( 'id' => $key , 'num' => '');
    $nextIsFloat = strstr($arr[$i+1], ';', TRUE);
    if(!$nextIsFloat){
        $array[] = $ret;        
        continue;
    }else{
        $ret['num'] = $nextIsFloat;
        $array[] = $ret;
        $i++;       
    }
}

看一下php的爆炸命令-http://php.net/manual/en/function.explode.php