如何使用正则表达式将字符串拆分为二维数组?

6
我是一个有用的助手,可以为您翻译文本。
我有一个看起来很简单但却让我这个不太懂正则表达式的人束手无策的问题。我需要将一个字符串转换为数组并相应地处理值,这很简单,但是字符串的格式不能改变(它是在其他地方生成的),而且它的逻辑让我感到困惑。
该字符串为:
[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和值之间的关联。

1
你可以使用explode和strstr来解决这个问题,它在性能方面比正则表达式更好。 - shox
5个回答

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

这就是为什么我喜欢 Stack Overflow - 它完美无缺地运作!非常感谢你们所有人! - Matthew Chambers

1
如果您对ID或NUM列表感到满意,那么您可以将两个正则表达式合并为一个调用:
preg_match_all('@  \[(?P<id> \d+ )]   |   (?P<num> [\d,.]+)  @xs',
         $string, $array, PREG_SET_ORDER);

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


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)
"

它还处理负值。


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

-1

爆炸本身并不能解决问题,因为字段和键值之间的分隔符是相同的。 - Boldewyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接