【问题标题】:PHP parse Ping command output with preg_matchPHP 使用 preg_match 解析 Ping 命令输出
【发布时间】:2022-01-15 18:20:11
【问题描述】:

我想在 Linux 中解析 ping 命令的输出。 我当前的代码工作正常,唯一的问题是它只解析第一个结果。 我想改变它来解析每一行。

红色标记的行也应该被解析:https://i.imgur.com/GDE19Xl.png 我必须改变什么才能做到这一点?

这是我当前的正则表达式: https://regex101.com/r/uH0XwP/1

这是当前的 PHP 代码:

$re = '/^PING\b[^(]*\(([^)]*)\)\s([^.]*)\..*?^(\d+\sbytes).*?icmp_seq=(\d+).*?ttl=(\d+).*?time=(.*?ms).*?(\d+)\spackets\stransmitted.*?(\d+)\sreceived.*?(\d+%)\spacket\sloss.*?time\s(\d+ms).*?=\s([^\/]*)\/([^\/]*)\/([^\/]*)\/(.*?)\sms/ims';
$str = 'PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=0.816 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=0.883 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=58 time=0.743 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=58 time=0.613 ms

--- 1.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3033ms
rtt min/avg/max/mdev = 0.613/0.763/0.883/0.105 ms
';

preg_match($re, $str, $matches, PREG_OFFSET_CAPTURE, 0);

// Print the entire match result
var_dump($matches);

非常感谢。 致以最诚挚的问候

【问题讨论】:

  • 这可能不是你想要的,但我会将其分解为每行规则,将 ping 结果分成几行并循环遍历它们执行 if preg_match 测试。它感觉不那么雄辩,但它更容易调试和推理。您还可以记录与您的模式不匹配的单行以查找边缘情况。

标签: php regex preg-match preg-match-all


【解决方案1】:

如果您的数据是这样的结构,您可以使用\G

(?:^PING\b[^(]*\(([^)]*)\)\s([^.]*)\..*|\G(?!^))\R^(\d+\sbytes).*?icmp_seq=(\d+).*?ttl=(\d+).*?time=(.*?ms).*(?:\s+---.*\R(\d+)\spackets\stransmitted.*?(\d+)\sreceived.*?(\d+%)\spacket\sloss.*?time\s(\d+ms)\R.*=\s([^\/]*)\/([^\/]*)\/([^\/]*)\/(.*?)\sms)?

Regex demo

在您的模式中,.*? 多次出现,也可能被更具体的部分替换,例如空格或带有可选小数部分的数字

(?:^PING\b[^(]*\(([^)]*)\)\s([^.]*)\.|\G(?!^))\R(\d+\sbytes).*?icmp_seq=(\d+)\h+ttl=(\d+).*?time=(\d+(?:\.\d+)?\h+ms).*(?:\s+---.*\R(\d+)\spackets\stransmitted.*?(\d+)\sreceived,\h*(\d+%)\spacket\sloss,\h+time\s(\d+ms)\R.*=\s(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\sms)?

然后使用 preg_match_all 值在第 3 组 - 第 6 组中

PHP demo

另一种选择是匹配捕获组中的重复数据,并分别处理这些行。在下一个模式中,捕获组 3 包含您可以在第二步中单独解析的重复行。

^PING\b[^(]*\(([^)]*)\)\s([^.]*)\.\R(\d+\sbytes.*?icmp_seq=\d+\h+ttl=\d+\h+time=\d+(?:\.\d+)?\h+ms(?:\R\d+\sbytes.*?icmp_seq=\d+\h+ttl=\d+\h+time=\d+(?:\.\d+)?\h+ms)*)\R+---.*\R(\d+)\spackets\stransmitted.*?(\d+)\sreceived,\h*(\d+%)\spacket\sloss,\h+time\s(\d+ms)\R.*=\s(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)\sms

查看另一个regex demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多