首页 > 解决方案 > preg_match_all 获取表达式的结尾

问题描述

我有几行:

[3G*2110620000*000A*UD]
[3G*2110620000*000A*LK][3G*2110620000*000A*LK,0,0,100]
[3G*2110620000*000A*LK,100]
[EL*2110620006*000A*LK,0,0],100]]]

结果我需要得到一个数组:

Array(
    [0] => Array
        (
            [Manufacture] => 3G
            [DeviceId] => 2110620000
            [Length] => 000A
            [Command] => UD
        ),
    [1] => Array
        (
            [Manufacture] => 3G
            [DeviceId] => 2110620000
            [Length] => 000A
            [Command] => LK
        ),
    [2] => Array
        (
            [Manufacture] => 3G
            [DeviceId] => 2110620000
            [Length] => 000A
            [Command] => LK
            [Parameters] => 0,0,100
        ),
    [3] => Array
        (
            [Manufacture] => 3G
            [DeviceId] => 2110620000
            [Length] => 000A
            [Command] => LK
            [Parameters] => 100
        ),
    [4] => Array
        (
            [Manufacture] => 3G
            [DeviceId] => 2110620000
            [Length] => 000A
            [Command] => LK
            [Parameters] => 0,0],100]]
        ),
)

每行可以包含一个或多个命令。

  1. 该命令以“[”开头并以“]”结尾。
  2. 该命令必须在“[”之后包含制造商名称“3G”或“EL”。
  3. 接下来是“*”分隔符。
  4. 接下来是一个 10 位数字,即设备标识符。
  5. 接下来是一个 4 字节的数据包长度。
  6. 接下来是命令的名称(可以是任意长度)。
  7. 接下来是“,”分隔符。
  8. 接下来是命令参数(它们可能不存在,它们可以包含任何字符,包括“]”和“[”)。

我正在尝试为这些情况编写一个正则表达式,但我无法突出显示参数。

我试过了

\[(?P<Manufacture>3G|EL)\*(?P<DeviceId>[0-9]{10})\*(?P<Length>[A-Z0-9]{4})\*(?P<Command>.+)[\]|,]{1}(?P<Parameters>.*)\]?

演示:https ://regex101.com/r/Iq2Xf4/2

标签: phpregexpreg-match-all

解决方案


比赛应以结束结束,]但该Parameters组也可以包含[]

一种选择是匹配尽可能少的字符,直到到达以 3G 或 EL 或右方括号后的字符串结尾的另一部分。

\[(?P<Manufacture>3G|EL)\*(?P<DeviceId>[0-9]{10})\*(?P<Length>[A-Z0-9]{4})\*(?P<Command>[^[,\r\n]*)(?:,(?P<Parameters>.*?(?=](?:\[(?:3G|EL)|$))))?]

解释

  • \[匹配[
  • (?P<Manufacture>3G|EL)\*命名组Manufacture匹配3GEL*
  • (?P<DeviceId>[0-9]{10})\*命名组DeviceId匹配 10 位数字和*
  • (?P<Length>[A-Z0-9]{4})\*命名小组Length赛 4 次 AZ 或 0-9 之一
  • (?P<Command>[^[,\r\n]*)命名组Command匹配[后跟除[ ,或换行符之外的任何字符
  • (?:非捕获组
    • ,(?P<Parameters>.*?,在组中尽可能少地匹配 a后跟任何字符Parameters
    • (?=](?:\[(?:3G|EL)|$))肯定的前瞻来断言右边的内容是字符串的结尾或[3G结尾[EL
  • )?关闭非捕获组并使其可选
  • ]比赛结束]

正则表达式演示


推荐阅读