bash - 解析多行程序输出
问题描述
我最近一直在做一些实验室任务,为了很好地收集和分析结果,我准备了一个 bash 脚本来自动化我的工作。这是我第一次尝试创建这样的脚本,因此它并不完美,我的问题与改进它密切相关。
该程序的示例输出如下所示,但我想让它更通用以用于更多目的。
>>> VARIANT 1 <<<
Random number generator seed is 0xea3495cc76b34acc
Generate matrix 128 x 128 (16 KiB)
Performing 1024 random walks of 4096 steps.
> Total instructions: 170620482
> Instructions per cycle: 3.386
Time elapsed: 0.042127 seconds
Walks accrued elements worth: 534351478
我想收集的所有数据总是在不同的行中。我的第一次尝试是运行同一个程序两次(或更多次,具体取决于数据量),然后在每次运行中使用 grep 通过查找关键字来提取我需要的数据。这是非常低效的,因为可能有一些可能解析一次运行的整个输出,但我想不出任何想法。目前脚本是:
#!/bin/bash
write() {
o1=$(./progname args | grep "Time" | grep -o -E '[0-9]+.[0-9]+')
o2=$(./progname args | grep "cycle" | grep -o -E '[0-9]+.[0-9]+')
o3=$(./progname args | grep "Total" | grep -o -E '[0-9]+.[0-9]+')
echo "$1 $o1 $o2 $o3"
}
for ((i = 1; i <= 10; i++)); do
write $i >> times.dat
done
值得一提的是,echo
在一行中生成结果至关重要,因为我稍后使用 gnuplot 并且在列中包含数据非常适合该用途。样本输出应为:
1 0.019306 3.369 170620476
2 0.019559 3.375 170620475
3 0.021971 3.334 170620478
4 0.020536 3.378 170620480
5 0.019692 3.390 170620475
6 0.020833 3.375 170620477
7 0.019951 3.450 170620477
8 0.019417 3.381 170620476
9 0.020105 3.374 170620476
10 0.020255 3.402 170620475
我的问题是:如何改进脚本以仅在一次程序执行中收集此类数据?
解决方案
您可以awk
在此处使用并将值放入数组中,然后通过 index 访问它们,1
以防您想在单个命令中执行此操作。2
3
myarr=($(your_program args | awk '/Total/{print $NF;next} /cycle/{print $NF;next} /Time/{print $(NF-1)}'))
或使用以下命令将所有元素强制打印到一行中,如果有人使用"
它来保持新行对值的安全,则不会出现新行。
myarr=($(your_program args | awk '/Total/{val=$NF;next} /cycle/{val=(val?val OFS:"")$NF;next} /Time/{print val OFS $(NF-1)}'))
说明:添加awk
上述程序的详细说明。
awk ' ##Starting awk program from here.
/Total/{ ##Checking if a line has Total keyword in it then do following.
print $NF ##Printing last field of that line which has Total in it here.
next ##next keyword will skip all further statements from here.
}
/cycle/{ ##Checking if a line has cycle in it then do following.
print $NF ##Printing last field of that line which has cycle in it here.
next ##next keyword will skip all further statements from here.
}
/Time/{ ##Checking if a line has Time in it then do following.
print $(NF-1) ##Printing 2nd last field of that line which has Time in it here.
}'
要访问您可以使用的单个项目,例如:
echo ${myarr[0]}
,echo ${myarr[1]}
和echo ${myarr[2]}
,Total
和cycle
分别time
。
如果需要,通过循环访问所有元素的示例:
for i in "${myarr[@]}"
do
echo $i
done
推荐阅读
- python - 如何用python==2.7.12创建conda虚拟环境
- clojure - 我在 clojure 中对这个 SICP 问题做错了什么?
- python - 如何在操作之前检查 xpath 是否可用?
- css - 冻结/锁定左三列
- javascript - 您如何正确输入此倒数计时器代码?
- c# - 实例化一个预制件,然后向它添加一个力(Projectile) - Unity
- java - 导入 com.google 无法解析 VSCode
- java - 无法在浏览器或终端中显示流数据
- node.js - 按顺序调用错误的 Express API 资源
- python - SQL语法问题——转义单引号和百分号