【问题标题】:Extracting the parts of string into array php将字符串的部分提取到数组php中
【发布时间】:2018-06-13 20:43:17
【问题描述】:

我有一个字符串需要分解并获取信息。

示例字符串:

"20' Container 1, 40' Open Container 1, 40-45' Closed Container 3, container roll 10, container lift 50"

首先我通过, 分解字符串并得到

"20' Container 1"
"40' Open Container 1"
"40-45' Closed Container 3"

现在我也想分解已经分解的数组,以便得到以下格式的结果

array[
    0 => [
        0 => "20'"
        1 => "Container"
        2 => "1"
        ]
    1 => [
        0 => "40'"
        1 => "Open Container"
        2 => "1"
        ]
    2 => [
          0=> container roll
          1=> 10
         ]
    3=> [
         0=> container lift
         1 => 50
        ]
    ]

字符串可能会有所不同,但会决定格式相同,例如length type number 其中length 是可选的,

我在做

$pattern = '/([\d-]*\')\s(.*)\s(\d+)/';
            foreach (explode(', ', $equipment->chassis_types) as $value) {
                preg_match($pattern, $value, $matches); // Match length, type, number
                $result[] = array_slice($matches, 1);   // Slice with offset 1
                $equipment->tokenized   =   $result;
            }

我明白了

Array
(
    [0] => Array
        (
            [0] => 20'
            [1] => container
            [2] => 10
        )

    [1] => Array
        (
            [0] => 40'
            [1] => open container
            [2] => 10
        )

    [2] => Array
        (
            [0] => 40-45'
            [1] => closed container
            [2] => 20
        )

    [3] => Array
        (
        )

    [4] => Array
        (
        )

)

【问题讨论】:

  • 那之后你想做什么
  • 我想要我已经解释过的结果数组
  • 预期结果数组中的数组索引 3 和 4 怎么样
  • 抱歉,编辑了问题
  • 类似这样的东西:regex101.com/r/06yaue/1 ?这里也不需要拆分。

标签: php arrays regex string preg-match


【解决方案1】:

你可以参考给定的例子

<?php

$string = "20' Container 1, 40' Open Container 1, 40-45' Closed Container 3, container roll 10, container lift 50";

$regex = "~
        (?:(?P<group1>\d+(?:-\d+)?')\h*)?
        (?P<group2>(?i:[a-z]+\h?)+)\h+
        (?P<group3>\d+(?:'')?)
        ~x";

if (preg_match_all($regex, $string, $matches, PREG_SET_ORDER)) {
    print_r($matches);
}
?>

a demo on regex101.com


这产生:
Array
(
    [0] => Array
        (
            [0] => 20' Container 1
            [group1] => 20'
            [1] => 20'
            [group2] => Container
            [2] => Container
            [group3] => 1
            [3] => 1
        )

    [1] => Array
        (
            [0] => 40' Open Container 1
            [group1] => 40'
            [1] => 40'
            [group2] => Open Container
            [2] => Open Container
            [group3] => 1
            [3] => 1
        )

    [2] => Array
        (
            [0] => 40-45' Closed Container 3
            [group1] => 40-45'
            [1] => 40-45'
            [group2] => Closed Container
            [2] => Closed Container
            [group3] => 3
            [3] => 3
        )

    [3] => Array
        (
            [0] => container roll 10
            [group1] => 
            [1] => 
            [group2] => container roll
            [2] => container roll
            [group3] => 10
            [3] => 10
        )

    [4] => Array
        (
            [0] => container lift 50
            [group1] => 
            [1] => 
            [group2] => container lift
            [2] => container lift
            [group3] => 50
            [3] => 50
        )

)


核心正则表达式是
(?:                               # non-capturing group
    (?P<group1>\d+(?:-\d+)?')\h*  # group1 = digits, 1+ (-other digits), optionally
)?                                # make the whole group optional
(?P<group2>(?i:[a-z]+\h?)+)\h+    # group2 = [a-zA-Z]+ horizontal whitespaces, no digits
(?P<group3>\d+(?:'')?)            # group3 = other digits + '', eventually

【讨论】:

    【解决方案2】:

    假设只有length 可以丢失,您可以尝试使用我从您现有的模式中修改的这个模式。加上array_filter() 函数从每个$matches 中删除空元素

    $pattern = '/([\d-]*\')?\s?(\D+)\s(\d+)/';
    foreach (explode(', ', $equipment->chassis_types) as $value) {
        preg_match($pattern, $value, $matches);
        $result[] = array_slice(array_filter($matches), 1);
    }
    $equipment->tokenized = $result;
    

    修改你的模式:

    • ? 在第一个捕获组之后,因此如果不存在可以跳过它
    • /s? 如果第一组不存在,也可以跳过第一个空格
    • (.*) 更改为(\D+) 以匹配任何非数字字符(假设type 不包含数字)

    注意:我将$equipment-&gt;tokenized = $result; 行移到循环外只设置一次,而不是在循环内重复设置

    【讨论】:

      【解决方案3】:

      我认为我最同意 Erwin 的回答,但尽管这不是一项验证任务,但我喜欢 Jan 的回答在定义范围“长度”子字符串和 Erwin's answer will match ' 1. 方面做得更好,没有迹象表明制表符或换行符存在于输入字符串中,因此适合使用文字空间。将正则表达式模式用双引号括起来意味着不需要转义模式中的撇号。作为记录,Andreas 的模式是不正确的,因为它无法正确匹配“长度”子字符串,并且在“类型”子字符串中包含不需要的空格。

      这是我用来解析提供的输入的内容:(Demo) (Pattern Demo)

      $string = "20' Container 1, 40' Open Container 1, 40-45' Closed Container 3, container roll 10, container lift 50";
      
      preg_match_all(
          "~(\d+(?:-\d+)?')? (\D+) (\d+)~",
          $string,
          $matches,
          PREG_SET_ORDER
      );
      
      print_r($matches);  // use var_export() to show that no spaces are captured
      

      模式说明:

      1. 匹配一位或多位数字,然后可选地匹配连字符后跟一位或多位数字,然后匹配撇号。这整个捕获的序列是可选的。 (Length)
      2. 匹配但不捕获一个空格。
      3. 捕获一个或多个非数字字符。 (Type)
      4. 匹配但不捕获一个空格。
      5. 捕获一位或多位数字。 (Number)

      【讨论】:

        【解决方案4】:

        您可以使用* 使第一个数字和' 可选。

        $str = '20\' Container 1, 40\' Open Container 1, 40-45\' Closed Container 3, container roll 10, container lift 50';
        preg_match_all('/(\d*\'*)\s([a-zA-Z ]+)(\d+)/', $str, $matches);
        var_dump($matches);
        

        这给出了这样的输出:

        array(4) {
          [0]=>
          array(5) {
            [0]=>
            string(15) "20' Container 1"
            [1]=>
            string(20) "40' Open Container 1"
            [2]=>
            string(22) "45' Closed Container 3"
            [3]=>
            string(18) " container roll 10"
            [4]=>
            string(18) " container lift 50"
          }
          [1]=>
          array(5) {
            [0]=>
            string(3) "20'"
            [1]=>
            string(3) "40'"
            [2]=>
            string(3) "45'"
            [3]=>
            string(0) ""
            [4]=>
            string(0) ""
          }
          [2]=>
          array(5) {
            [0]=>
            string(10) "Container "
            [1]=>
            string(15) "Open Container "
            [2]=>
            string(17) "Closed Container "
            [3]=>
            string(15) "container roll "
            [4]=>
            string(15) "container lift "
          }
          [3]=>
          array(5) {
            [0]=>
            string(1) "1"
            [1]=>
            string(1) "1"
            [2]=>
            string(1) "3"
            [3]=>
            string(2) "10"
            [4]=>
            string(2) "50"
          }
        }
        

        要获得更接近您想要的数组,您可以使用数组列将匹配项按您喜欢的方式分组。

        $str = '20\' Container 1, 40\' Open Container 1, 40-45\' Closed Container 3, container roll 10, container lift 50';
        preg_match_all('/(\d*\'*)\s([a-zA-Z ]+)(\d+)/', $str, $matches);
        unset($matches[0]); // remove full match as it's not needed.
        
        $res =[];
        foreach($matches[1] as $key => $val){
            $res[] = array_column($matches, $key);
        }
        var_dump($res);
        

        https://3v4l.org/4rGod

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-11-08
          • 2012-09-23
          • 2020-02-05
          • 2021-11-26
          • 1970-01-01
          • 2010-12-26
          • 2012-03-28
          相关资源
          最近更新 更多