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

相关推荐
wxin_VXbishe4 小时前
springboot在线课堂教学辅助系统-计算机毕业设计源码07741
java·c++·spring boot·python·spring·django·php
苏琢玉5 小时前
被问性能后,我封装了这个 PHP 错误上报工具
php·composer
郑州光合科技余经理6 小时前
乡镇外卖跑腿小程序开发实战:基于PHP的乡镇同城O2O
java·开发语言·javascript·spring cloud·uni-app·php·objective-c
hzbigdog7 小时前
php的CSV大数据导入导出的通用处理类
大数据·后端·php
何憶树之長青13 小时前
Kernel
开发语言·php
bin915313 小时前
PHP文档保卫战:AI自动生成下的创意守护与反制指南
开发语言·人工智能·php·工具·ai工具
蒋星熠14 小时前
爬虫中Cookies模拟浏览器登录技术详解
开发语言·爬虫·python·正则表达式·自动化·php·web
JaguarJack15 小时前
用 LaraDumps 高效调试 PHP 和 Laravel
后端·php
白山云北诗1 天前
网站被攻击了怎么办?如何进行DDoS防御?
开发语言·网络安全·php·ddos·防ddos·防cc
真正的醒悟1 天前
什么是安全设备组网
服务器·数据库·php