背景
刚开始使用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"
}
}
提取遇到的问题:
-
如果是简单的按空格分割,时间字段中间带有空格的,会被切成两段,如果表头有多个单词也可能出现分段;
-
发现字段直接是按两个空格分隔, 可以考虑用两个空格作为分割符, 可是会遇到Tags列可能是空的,到时表头与行的列对不上
解决思路
-
先将文本按行分割
-
找到表头行,及表格内容行
-
表头行通过双空格作为分割符分割,取得列名及其列宽
-
按列名及列宽提取每个表格内容行
-
组装数组
实现代码
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输出了,以上的代码就不需要了,在此记录一下,留个痕:)