PHP实现终端表格提取

背景

刚开始使用restic想要获取终端的输出数据,默认的终端信息如下示例

bash 复制代码
restic snapshots

repository 5816ba52 opened (version 2, compression level auto)
ID        Time                 Host        Tags        Paths       Size
-----------------------------------------------------------------------
753dd093  2024-11-22 12:04:57  kylinv10                /root/test  0 B
-----------------------------------------------------------------------
1 snapshots

希望得到的数据是表格转为数组

php 复制代码
array(1) {
  [0]=>
  array(6) {
    ["ID"]=>
    string(8) "753dd093"
    ["Time"]=>
    string(19) "2024-11-22 12:04:57"
    ["Host"]=>
    string(8) "kylinv10"
    ["Tags"]=>
    string(0) ""
    ["Paths"]=>
    string(10) "/root/test"
    ["Size"]=>
    string(3) "0 B"
  }
}

提取遇到的问题:

  1. 如果是简单的按空格分割,时间字段中间带有空格的,会被切成两段,如果表头有多个单词也可能出现分段;

  2. 发现字段直接是按两个空格分隔, 可以考虑用两个空格作为分割符, 可是会遇到Tags列可能是空的,到时表头与行的列对不上

解决思路

  1. 先将文本按行分割

  2. 找到表头行,及表格内容行

  3. 表头行通过双空格作为分割符分割,取得列名及其列宽

  4. 按列名及列宽提取每个表格内容行

  5. 组装数组

实现代码

php 复制代码
<?php
// 给定的文本
$text = "repository 5816ba52 opened (version 2, compression level auto)
ID        Time                 Host        Tags        Paths       Size
-----------------------------------------------------------------------
753dd093  2024-11-22 12:04:57  kylinv10                /root/test  0 B
-----------------------------------------------------------------------
1 snapshots";

function keys($line)
{
    $items = explode('  ', $line);
    $end   = 0;
    $keys  = [];
    $width = [];
    foreach ($items as $n => $item) {
        if (strlen($item) == 0) {
            $end += 2;
            continue;
        }
        $keys[] = trim($item);
        if ($n > 0 and $items[$n - 1] == '') {
            $end += 2;
        }
        $width[] = $end;
        $end += strlen($item);
    }
    $width[] = $end;
    $res     = [];
    foreach ($keys as $n => $key) {
        $res[$key] = [$width[$n], $width[$n + 1]];
    }
    return $res;
}

function rowSplit($keys, $line)
{
    $res = [];
    foreach ($keys as $key => $step) {
        $res[$key] = trim(substr($line, $step[0], $step[1] - $step[0]));
    }
    return $res;
}

// 将字符串按行分割
$lines = explode("\n", $text);

$res = [];

$th   = [];
$tr   = [];
$pick = false;
foreach ($lines as $n => $line) {
    if (str_starts_with($line, '----')) {
        if ($pick) {
            break;
        }
        if (empty($th)) {
            $th   = keys($lines[$n - 1]);
            $pick = true;
            continue;
        }
    }
    if ($pick) {
        $tr    = rowSplit($th, $line);
        $res[] = $tr;
    }
}


// 打印结果
var_dump($res);

后记

后来深入了解restic后,发现传参--json就可以得到json输出了,以上的代码就不需要了,在此记录一下,留个痕:)

相关推荐
郑州光合科技余经理9 小时前
海外版多语言团购系统架构:主数据互通与核销边界
java·开发语言·前端·后端·系统架构·php·ai编程
heimeiyingwang15 小时前
【架构实战】Kubernetes网络模型深度解析:从Pod通信到Ingress网关实战
开发语言·架构·php
运维行者_16 小时前
预测性云监控怎么做?AI驱动的7大核心能力与落地路径
服务器·开发语言·网络·数据库·人工智能·python·php
eggrall18 小时前
Socket编程UDP
网络协议·udp·php
牛马也想出海1 天前
亚马逊爬虫代理IP:IP类型选择与配置指南
开发语言·php
梦梦代码精1 天前
基于UniApp+Vue3+ThinkPHP 8,这套知识付费系统的架构设计有点东西
java·低代码·docker·uni-app·开源·php
lxw18449125141 天前
PHP5、PHP7、PHP8 版本核心区别与特性
人工智能·php
AI直播技术杂谈1 天前
直播画面突然模糊了,排查了三个小时
开发语言·php
heimeiyingwang2 天前
【架构实战】可观测性三支柱实战:Metrics、Logging、Tracing 如何统一落地
开发语言·架构·php
CRMEB2 天前
商城大促活动策划全流程:从定目标到复盘四阶段
java·开发语言·人工智能·ai·开源·php