这是一个 SOS 问题。我的教授要求我从一位前博士后(他向我解释了其工作原理)遗赠给我们的长期运行的模拟代码中获取输出。
我做了一些小规模的试运行,一切都很顺利。然后我在大约一个月前开始了完整的模拟,并从那时起一直在连续运行。但就在几分钟前,由于一些内存问题,程序在将格式化的表格输出写入磁盘之前崩溃了。
幸运的是,我启用了中间结果的终端回显,并将回滚历史设置为一个较大的值。我通过进入回滚模式并将整个终端转储复制到文本文件中(并制作了它的备份副本)来设法挽救部分输出。
现在,这个终端输出非常详细(出于调试目的故意设置如此)。以下是抢救的终端输出文本文件的快照(我们称之为terminal_output.txt
)
1 Linear search iteration no. 1 begins: Attempting to blah blah with 1 ...
2 blah blah
3 blah
4 blah blah blah
5 lorem ipsum
.........
........
75 Success with 128 blah ....
76 blah blah
77 blah blah
78 result_flag: 1, exit_reason: 6
79 blah
80 Completed optimal computation with T_init = 25.00 degC & T_sink = 35.00 degC
然后这个精确的模式就会重复。例如,
81 Linear search iteration no. 2 begins: Attempting to blah blah with 1 ...
82 blah
......
95 Success with 307 blah ....
......
......
100 Completed optimal computation with T_init = 30.00 degC & T_sink = 40.00 degC
我的要求是提取以下信息以生成表格输出,例如:
25 35 128
30 40 307
...........
...........
T_init
即第一列和第二列分别来自与和对应的数值T_sink
,来自以 开头的那些行Completed
。第三列是从 开始的行的数值(如果有帮助的话,Success
总是在前面 5 行)。Completed
列之间的任何分隔符都是可接受的 - 无论是空格、制表符还是逗号。
我希望使用标准 *nix 实用程序(例如grep
、sed
和awk
甚至 )来本地执行此操作vi/vim
。串在一起的管道式单行或bash
脚本都可以。如果有必要,我也愿意使用python
或perl
其他脚本语言。
答案1
这本质上是捕获您想要的部分并丢弃您不需要的部分的问题。例如,使用sed
,您可以捕获整Success
数值并将其复制到保留空间(H),检索并附加它(G) 到该行捕获的数字Completed
:
sed -nE \
-e '/Success/ {s/.* ([0-9]+).*/\1/; h;}' \
-e '/Completed/{G; s/.*T_init = ([0-9]+)\.00 degC & T_sink = ([0-9]+).*\n/\1 \2 /; p;}
' terminal_output.txt
Perl 提供了一种更具表现力的语法,恕我直言,它更具可读性:
perl -lne '
our $a = $1 if /Success.*?(\d+)/; print join " ", /(\d+)\.\d+/g, $a if /Completed/
' terminal_output.txt
产生所需的输出
25 35 128
30 40 307
答案2
POSIX 兼容sed
:
grep -e 'Success' -e 'Completed' your_file | sed 'N;s/Success with \([[:digit:]]\+\).*T_init = \([^[:space:]]\+\).*T_sink = \([^[:space:]]\+\).*/\2 \3 \1/;s/\.00//g'
GNU sed
:(其中至少在 CentOS 上的 4.2.2 中.
不匹配)\n
grep -e 'Success' -e 'Completed' your_file | sed 'N;s/Success with \([[:digit:]]\+\).*\n.*T_init = \([^[:space:]]\+\).*T_sink = \([^[:space:]]\+\).*/\2 \3 \1/;s/\.00//g'
抓取包含 和 的行Success
,Completed
然后在两行上进行操作(比必要的更明确)拉出您关心的三个字段并将它们排序到一行中。
这只会截断.00
任何数字,保留任何重要的小数部分(包括类似 的内容12.20
,仍然会有单个尾随零)。
...
警告如果其中一些行包含Completed
或,它将不起作用Success
答案3
一个快速awk
命令应该可以帮助您开始:
awk '$2 ~ /Success/{a=$4;next}; $2 ~ /Completed/{b=$8;c=$13;print a,b,c}' terminal_output.txt
Success
如果一行之前有多行Completed
等,这将不起作用。