【问题标题】:How to split string to 2D array with Regex?如何使用正则表达式将字符串拆分为二维数组?
【发布时间】:2011-12-29 17:31:47
【问题描述】:

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

字符串是:

[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 和 value 之间的相关性。

【问题讨论】:

  • 你可以用explode&strstr解决这个问题,它在性能方面比正则表达式更好。

标签: php regex arrays string


【解决方案1】:

看看php的explode命令—— http://php.net/manual/en/function.explode.php

【讨论】:

  • 好吧,单独爆炸没有帮助,因为字段和 key=>value 之间的分隔符是相同的。
【解决方案2】:

示例:

<?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 的原因 - 它绝对完美!非常感谢大家!
【解决方案3】:

如果您对 ID 或 NUM 列表感到满意,那么您可以将两个工作正则表达式组合到一个调用中:

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

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

【讨论】:

    【解决方案4】:

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

    它还处理负值。

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-22
        • 1970-01-01
        • 2016-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多