从纯文本文件中的复杂模式中提取数字数据并生成表格输出

从纯文本文件中的复杂模式中提取数字数据并生成表格输出

这是一个 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 实用程序(例如grepsedawk甚至 )来本地执行此操作vi/vim。串在一起的管道式单行或bash脚本都可以。如果有必要,我也愿意使用pythonperl其他脚本语言。

答案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'

抓取包含 和 的行SuccessCompleted然后在两行上进行操作(比必要的更明确)拉出您关心的三个字段并将它们排序到一行中。

这只会截断.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等,这将不起作用。

相关内容