为了账号安全,请及时绑定邮箱和手机立即绑定

如何在正则表达式中重复分组

如何在正则表达式中重复分组

PHP
萧十郎 2021-12-24 15:26:20
我正在搜索从这样的文本中提取坐标:"xxxxxxx 453740N0093059E 453356N0093503E 453225N0094201E 453238N0095044E 453351N0095543E 453618N0095826E 453740N0093059 yyyyyyy 453351N0095543E 453740N0093059 pppppppp 453740N0093059E 453740N0093059 nnnnnn nnnnnn 453618N0095826E 453740N0093059 453225N0094201E ...."其中 xxx、yyy、nnn 和 ppp 可以是任何单词。我需要提取 [0-9]{6}N[0-9]{7}E 形式的任何内容并创建一组连续坐标,以便我可以获得:1: 453740N0093059E 453356N0093503E 453225N0094201E 453238N0095044E 453351N0095543E 453618N0095826E 453740N0093059 2: 453351N0095543E 453740N0093059 3: 453740N0093059E 453740N0093059 4: 453618N0095826E 453740N0093059 453225N0094201E ....5: ......不知道存在多少个坐标组。我试图实现正则表达式preg_match_all("/[0-9]{6}N[0-9]{7}E\s([0-9]{6}N[0-9]{7}E)*?/",$text,$res)但它返回的 Array 每个索引只有一个坐标,而不是一组连续的坐标。
查看完整描述

2 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

首先,E在您的模式中似乎是可选的,您需要使用?.


接下来,您将[0-9]{6}N[0-9]{7}E离开的部分分组\s,这已经阻止了正则表达式甚至尝试匹配连续的空白分隔子模式。您需要使用(?:\s[0-9]{6}N[0-9]{7}E?)*来匹配 0 个或多个空格序列,后跟坐标。


利用


preg_match_all('~(?<!\S)\d{6}N\d{7}E(?:\s\d{6}N\d{7}E?)*(?!\S)~', $s, $matches)

或者,如果坐标之间可以有 1 个以上的空格


preg_match_all('~(?<!\S)\d{6}N\d{7}E(?:\s+\d{6}N\d{7}E?)*(?!\S)~', $s, $matches)

                                         ^

请参阅正则表达式演示。注意(?<!\S)并(?!\S)确保仅在空格内或字符串的开头/结尾处匹配。如果不需要检查此条件,请删除。


请注意,您可能需要先收缩-&-标准化字符串中的所有空格,然后使用


$re = '~(?<!\S)\d{6}N\d{7}E(?:\s+\d{6}N\d{7}E?)*(?!\S)~';

$s = preg_replace('~\s+~u', ' ', $s);

if (preg_match_all($re, $s, $matches)) {

    print_r($matches[0]);

}


查看完整回答
反对 回复 2021-12-24
?
跃然一笑

TA贡献1826条经验 获得超6个赞

我的猜测是,也许您正在尝试编写一些简单的表达式,并针对您可能遇到的各种情况使用逻辑 OR 将它们连接起来,例如:


\b([0-9]{6}[NSWE]{1,2}[0-9]{7}[NSWE]{1,2})\b|\b([0-9]{6}[NSWE]{1,2}[0-9]{7})\b

虽然不确定。


测试

$re = '/\b([0-9]{6}[NSWE]{1,2}[0-9]{7}[NSWE]{1,2})\b|\b([0-9]{6}[NSWE]{1,2}[0-9]{7})\b/s';

$str = 'xxxxxxx 453740N0093059E 453356N0093503E

453225N0094201E 453238N0095044E 453351N0095543E 453618N0095826E

453740N0093059 yyyyyyy 453351N0095543E 453740N0093059

pppppppp 453740N0093059E 453740N0093059 nnnnnn

nnnnnn 453618N0095826E 453740N0093059 453225N0094201E ....';


preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);


$output = [];

$output["groups"] = [];

foreach ($matches as $key => $value) {

    if ($value[2]) {

        $output["groups"][2][$key] = $value[2];

    } else if ($value[1]) {

        $output["groups"][1][$key] = $value[1];

    } else {

        // The expression can be modified and

        // Other cases can be added here

        continue;

    }

}


var_dump($output["groups"]);

输出

array(2) {

  [1]=>

  array(10) {

    [0]=>

    string(15) "453740N0093059E"

    [1]=>

    string(15) "453356N0093503E"

    [2]=>

    string(15) "453225N0094201E"

    [3]=>

    string(15) "453238N0095044E"

    [4]=>

    string(15) "453351N0095543E"

    [5]=>

    string(15) "453618N0095826E"

    [7]=>

    string(15) "453351N0095543E"

    [9]=>

    string(15) "453740N0093059E"

    [11]=>

    string(15) "453618N0095826E"

    [13]=>

    string(15) "453225N0094201E"

  }

  [2]=>

  array(4) {

    [6]=>

    string(14) "453740N0093059"

    [8]=>

    string(14) "453740N0093059"

    [10]=>

    string(14) "453740N0093059"

    [12]=>

    string(14) "453740N0093059"

  }

}

如果你想探索/简化/修改表达式,它已在regex101.com 的右上角面板中进行了 解释。如果您愿意,您还可以在此链接中观看它如何与某些示例输入匹配。


正则表达式电路

jex.im可视化正则表达式:

//img1.sycdn.imooc.com//61c5766600012a0308630346.jpg

查看完整回答
反对 回复 2021-12-24
  • 2 回答
  • 0 关注
  • 304 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信