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

相关推荐
qq_433776424 小时前
【无标题】
开发语言·php
咖啡续命又一天4 小时前
PhpStorm 启用注释自动缩进
php·phpstorm
Arwen3036 小时前
SSL 加密证书助力企业构建安全的网络环境
网络·网络协议·tcp/ip·安全·php·ssl
幽络源小助理7 小时前
PHP虚拟商品自动发卡系统源码 – 支持文章付费阅读与自动发货
开发语言·php
solar应急响应11 小时前
域控宕机!如何强制夺取五大角色恢复业务?
开发语言·php
CS创新实验室13 小时前
《计算机网络》深入学:虚电路
服务器·计算机网络·php·虚电路
2501_9418771313 小时前
在法兰克福企业级场景中落地零信任安全架构的系统设计与工程实践分享
开发语言·php
hai742514 小时前
php+nginx在cookie中设置了HttpOnly属性
php
catchadmin14 小时前
PHP 8.5 管道操作符 (|>) 告别嵌套函数地狱,写出清晰的数据管道
php
Kratzdisteln14 小时前
【MVCD 3】
开发语言·php