【问题标题】:regex global to extract substrings from string [duplicate]正则表达式全局从字符串中提取子字符串[重复]
【发布时间】:2013-04-12 05:47:24
【问题描述】:

我正在尝试从标准 Oracle 连接字符串中提取 FQDN 和端口号。 我已经想出了如何单独提取 FQDN 和 PORT,但我正在寻找一个 php 正则表达式,它可以让我同时提取所有 FQDN 和 PORT。

示例连接字符串:

(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))

我的预期结果是一个数组:

[0][0] => FQDN1, [0][1] => 1234, 
[1][0] => FQDN2, [1][1] => 5678, 
[2][0] => FQDN3, [2][1] => 9012, 
[3][0] => FQDN4, [3][1] => 3456

你们的任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: php regex


    【解决方案1】:

    你可以像这样使用 preg_match_all:

    if (preg_match_all('~HOST=([^)\s]+).*?PORT=([^)\s]+)~', $str, $arr))
       print_r($arr);
    

    现场演示:http://ideone.com/btmeao

    【讨论】:

    • 这就是我所需要的,虽然我不明白为什么数组的第 0 个索引具有整个 HOST=...)(PORT=... 而我的数据位于索引位置 1和 2. 我原以为我的数据将从索引 0 开始。
    • 不过,这让我得到了我需要的东西。
    • @LegioX:根据 preg_match_all 的 PHP 手册:Orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on. 参见此处:php.net/manual/en/function.preg-match-all.php
    【解决方案2】:
    $str="(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))";
    preg_match_all('/\(HOST=(FQDN\d)\)\(PORT=(\d+)\)/', $str, $matches, PREG_SET_ORDER);
    foreach($matches as $k=>$match)
        array_shift($matches[$k]);
    

    使用 PREG_SET_ORDER 以您想要的方式排列它们。然后 array_shift 敲掉完整的匹配。

    http://ideone.com/yN07yP

    尽可能阅读文档:

    http://php.net/manual/en/function.preg-match-all.php

    【讨论】:

    • 该模式实际上是在渲染空白。我已经阅读了 preg_match_all 函数,但我忽略了 PREG_SET_ORDER 标志。非常感谢您提供可能的解决方案。我感谢所有的帮助。我花了一整天时间修改我的正则表达式,但无法让它正常工作。
    【解决方案3】:

    试试这个:

    $subject = <<<LOD
    (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))
    LOD;
    
    $pattern = '~\(HOST=([^)]+)\)\(PORT=(\d+)\)~';
    
    preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
    
    // removes the whole match (index 0) for each result to only let the capture groups
    foreach ($matches as &$match) {
        array_shift($match);
    }
    

    【讨论】:

    • 我希望我可以给所有正确的答案打上复选标记,但我只能打一个复选标记。您的模式还提供了必要的信息。我在阅读 preg_match_all 时忽略的 PREG_SET_ORDER 是锦上添花。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多