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输出了,以上的代码就不需要了,在此记录一下,留个痕:)

相关推荐
MartinYeung58 小时前
[论文学习]小型代码语言模型中的潜伏代理行为研究
学习·语言模型·php
P1Browser9 小时前
指纹浏览器安全吗?从浏览器环境隔离、数据存储到安全风险解析
网络·tcp/ip·安全·网络安全·github·php
数据知道10 小时前
PHP 代码审计实战——ThinkPHP、Laravel 历史漏洞模式深度剖析
android·网络·web安全·网络安全·php·laravel
郑州光合科技余经理11 小时前
本地生活平台搭建:统一订单表与多后台切换怎么拆
java·开发语言·前端·系统架构·uni-app·php·ai编程
虎王物联1 天前
PHP实现MQTT消息处理:物联网设备数据接收与指令下发
android·物联网·php
程序猿_极客2 天前
【免费】分享一套优质的基于Php+Mysql的电子购物网站的设计与实现,校园小卖部系统
数据库·mysql·php·购物商城系统
PHP实战开发录2 天前
PHP后台大文件导出内存溢出排查记录
性能优化·系统架构·php·开发
lskblog2 天前
Ubuntu 18.04 安装 LibreOffice(用于 Word 在线预览转换)
java·linux·python·ubuntu·word·php·laravel
-今昭-2 天前
OpenStack Dashboard 部署与图形化创建云主机实战指南
开发语言·php
那年窗外下的雪.2 天前
AIDC 学习日志|第 15 天|EVPN 多归属故障收敛与撤销机制
网络·学习·php