【问题标题】:Get numbers after dash "-" from an array and preserve dash in his original position. Regex从数组中获取破折号“-”之后的数字并将破折号保留在其原始位置。正则表达式
【发布时间】:2015-03-03 16:33:58
【问题描述】:

来自其他线程的用户帮助我弄清楚如何从数组中获取数字,但现在我无法获取“-”破折号之后的数字。让我向你展示我所拥有的东西,然后让你了解情况。

我有一个包含下一个内容的数组:

Array(
[0] => <tr><td>29/06/2015</td><td>19:35</td><td>12345 Column information</td><td>67899 Column information - 12</td><td>Information</td><td>More information</td></tr>
[1] => <tr><td>12/03/2015</td><td>10:12</td><td>98545 Column information</td><td>67659 Column information - 32</td><td>Information</td><td>More information</td></tr>
[2] => <tr><td>11/02/2015</td><td>12:40</td><td>59675 Column information</td><td>94859 Column information - 11</td><td>Information</td><td>More information</td></tr>
[3] => <tr><td>01/01/2015</td><td>20:12</td><td>69365 Column information</td><td>78464 Column information - 63</td><td>Information</td><td>More information</td></tr>
)

我终于知道如何获取每个数字(破折号“-”后面的数字除外):

$re = "/.*?(\\d+)\\s.*?(\\d+)\\s.*/m";
$str = "<tr><td>29/06/2015</td><td>19:35</td><td>12345 Column information</td><td>67899 Column information - 12</td><td>Information</td><td>More information</td></tr>";
$subst = "$1, $2";
$result = preg_replace($re, $subst, $str);

这是 $result;输出:

foreach($result as $finalresult) echo $finalresult.'<br>';

12345,67899
98545,67659
59675,94859
69365,78464

我对所有这些过程的期望并且无法弄清楚的是在破折号“-”之后也得到数字:

12345,67899-12
98545,67659-32
59675,94859-11
69365,78464-63

但这并没有在这里结束......当破折号“-”后面的数字低于 50 时,我需要转换 $result 输出。请参见下面的示例。 如果“-”之后的数字

    12345,67899-12 ------> 12345,67899-01
    98545,67659-32 ------> 12345,67899-03
    59675,94859-11 ------> 12345,67899-01
    52375,53259-49 ------> 12345,67899-04
    69365,73464-63 ------> 12345,67899-63
    89765,12332-51 ------> 12345,67899-51
    38545,54213-70 ------> 12345,67899-70

现在是我的头爆炸的时候!

在此之前非常感谢您的帮助。

【问题讨论】:

    标签: php html arrays regex numbers


    【解决方案1】:

    这可能是您正在寻找的。我稍微修改了你的正则表达式。 (.*?&lt;td&gt;){3} 将匹配第三个 &lt;td&gt; 之前的任何内容。子模式(?P&lt;first&gt;\d+) 等中的?P&lt;first&gt; 称为命名子模式,这使得它们的值很容易从$matches 数组中访问。

    $a = [
        '<tr><td>29/06/2015</td><td>19:35</td><td>12345 Column information</td><td>67899 Column information - 12</td><td>Information</td><td>More information</td></tr>',
        '<tr><td>12/03/2015</td><td>10:12</td><td>98545 Column information</td><td>67659 Column information - 32</td><td>Information</td><td>More information</td></tr>',
        '<tr><td>11/02/2015</td><td>12:40</td><td>59675 Column information</td><td>94859 Column information - 11</td><td>Information</td><td>More information</td></tr>',
        '<tr><td>01/01/2015</td><td>20:12</td><td>69365 Column information</td><td>78464 Column information - 63</td><td>Information</td><td>More information</td></tr>',
    ];
    
    $result = [];
    
    foreach ($a as $row) {
        $p = '#(.*?<td>){3}(?P<first>\d+).*?</td><td>(?P<second>\d+).*?(?P<third>\d+)#';
    
        if (preg_match($p, $row, $matches)) {
            if ($matches['third'] < 50) {
                $matches['third'] = '0'.$matches['third'][0];
            }
            $result[] =
                $matches['first'] . ',' .
                $matches['second'] . '-' .
                $matches['third'];
        }
    }
    print_r($result);
    

    输出:

    Array
    (
        [0] => 12345,67899-01
        [1] => 98545,67659-03
        [2] => 59675,94859-01
        [3] => 69365,78464-63
    )
    

    【讨论】:

    • 再次非常感谢您!! :)
    【解决方案2】:

    这将为您解决问题:

    $re = '/.*?(\d+)\s.*?(\d+)\s.*?-\s(\d+).*/';
    $str = "<tr><td>29/06/2015</td><td>19:35</td><td>12345 Column information</td><td>67899 Column information - 12</td><td>Information</td><td>More information</td></tr>";
    preg_match($re, $str, $matches);
    if ($matches[3]<50) $matches[3] = floor($matches[3]/10);
    $format = '%d,%d-%02d';
    $result = sprintf($format, $matches[1], $matches[2], $matches[3]);
    echo $result;
    

    请注意,为了便于阅读,我将您的 $re 更改为单引号而不是双引号,并且我使用 preg_match 而不是 preg_replace,因此我可以使用匹配的模式。

    为了向您解释正则表达式,有几件事情正在发生:

    • / 是正则表达式分隔符。
    • .*?. 告诉正则表达式匹配任何字符。 * 说要执行零次或多次,? 说要以“懒惰”的方式执行。 $re 末尾的普通 .* 匹配整个字符串的其余部分。
    • (\d+)\d 是一个通配符,告诉正则表达式匹配任何数字。 + 说“一次或多次”,() 说要捕获这个。第一个() 包围组是$matches[1]
    • \s:是任何空格字符的通配符。
    • -:是文字 - 字符。

    【讨论】:

    • 多么干净的代码,谢谢!! preg_match 和 $str 出现错误,因为我使用的是数组。通过将您的代码放入 foreach 来解决它。这是修复它的好方法吗?输出是正确的,但我不知道这是否是使用 preg_match 和数组的最佳方式。
    • 请您解释一下 $re 究竟是如何工作的?我想学习正则表达式而不是简单地复制代码:)
    • 正则表达式需要一段时间才能理解。从阅读PHP Documentation 开始,要真正掌握它们,试试live regex sandbox。我会在我的答案中添加对$re 的解释。
    • 再次感谢,非常感谢。多亏了你,我从正则表达式中学到了很多东西。我在将您的代码修改为另一个类似任务方面取得了一些不错的进展。我可以编辑这个帖子并问你这个问题吗?或者可能更好地创建另一个带有问题的帖子?
    • 您应该将这个已解决的问题留给我们,并在新线程中提出新问题。
    【解决方案3】:

    嗯...我不知道它是否有帮助,但我用 RegExr 做了这个,它很合适:

    (([0-9]+){5})|(- [0-9]{2})

    我希望你会发现它有些用处!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多