如何使用Regex将字符串拆分为2D数组?

时间:2011-11-15 17:12:44

标签: php regex arrays string

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

字符串是:

[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);

但失去了id和值之间的相关性。

5 个答案:

答案 0 :(得分:3)

示例:

<?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"
  }
}

答案 1 :(得分:1)

如果您对ID或NUM的列表感到满意,那么您可以将两个正在运行的正则表达式组合成一个调用:

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

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

答案 2 :(得分:1)

这样的东西?我的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)
"

它还会处理负值。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

它不是正则表达式方法,但它可能对你有用:(当然可以改进)

$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++;       
    }
}