如何一次从文件中提取多个值?

adh*_*ous 6 sed awk text-processing

我有一个来自模拟的巨大日志文件(大约 6GB)。在该文件的数百万行中,有两行在给定时间内频繁重复:

...
Max value of omega = 3.0355
Time = 0.000001
....
Max value of omega = 4.3644
Time = 0.000013
...
Max value of omega = 3.7319
Time = 0.000025
...
...
...
Max value of omega = 7.0695
Time = 1.32125
...
... etc.

Run Code Online (Sandbox Code Playgroud)

我想提取“欧米茄的最大值”和“时间”,并将它们作为列保存在一个文件中:

#time max_omega
0.000001 3.0355
0.000013 4.3644
0.000025 3.7319
...etc.
Run Code Online (Sandbox Code Playgroud)

我进行了如下操作:

# The following takes about 15 seconds
grep -F 'Max value of omega' logfile | cut -d "=" -f 2 > max_omega_file.txt  
Run Code Online (Sandbox Code Playgroud)

,“时间”也一样

# This also takes about 15 seconds
# Very important: match exactly 'Time =' because there other lines that contain the word 'Time'
grep -F 'Time =' logfile | cut -d "=" -f 2 > time.txt
Run Code Online (Sandbox Code Playgroud)

然后我需要使用该命令paste创建一个两列文件:Time.txt 作为第一列,“max_omega_file.txt”作为第二列。

如您所见,上述步骤中的时间翻了一番。我想知道是否有一个单一的解决方案可以在一次传递中获得相同的结果,这样我就可以节省一些时间?

αғs*_*нιη 10

sed -n '/^Max/ { s/^.*=\s*//;h; };
        /^Time/{ s/^.*=\s*//;G; s/\n/ /;p; }' infile
Run Code Online (Sandbox Code Playgroud)
  • match-run 语法/.../{ ... }:其中的
    命令{...}只会在与 regex/pattern 匹配的行上运行/.../

  • s/^.*=\s*//:
    删除所有内容=和空格(\s*如果有的话)。

  • h:
    将结果复制到保持空间

  • G:
    将保留空间附加到带有嵌入换行符的模式空间

  • s/\n/ /:
    用模式空间中的空格替换嵌入的换行符

  • p
    打印模式空间;你也可以P在这里使用命令。

    0.000001 3.0355
    0.000013 4.3644
    0.000025 3.7319
    1.32125 7.0695
    
    Run Code Online (Sandbox Code Playgroud)

@stevesliva提出的类似方法,用于s//<replace>/在最后一场比赛中进行替换:

sed -n '/^Max.*=\s*/ { s///;h; };
        /^Time.*=\s*/{ s///;G; s/\n/ /;p; }' infile
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最快的解决方案。 (2认同)

ste*_*ver 7

我不能保证它会更快,但你可以在 awk 中做这样的事情:

awk -F' = ' '$1=="Max value of omega" {omega = $2} $1=="Time" {print omega,$2}' file
Run Code Online (Sandbox Code Playgroud)


Ed *_*ton 5

$ awk 'BEGIN{print "#time", "omega"} /^Max value of omega =/{omega=$NF; next} /^Time =/{print $NF, omega}' file
#time omega
0.000001 3.0355
0.000013 4.3644
0.000025 3.7319
1.32125 7.0695
Run Code Online (Sandbox Code Playgroud)

但这可能会更快:

$ grep -E '^(Max value of omega|Time) =' file |
    awk 'BEGIN{print "#time", "omega"} NR%2{omega=$NF; next} {print $NF, omega}'
#time omega
0.000001 3.0355
0.000013 4.3644
0.000025 3.7319
1.32125 7.0695
Run Code Online (Sandbox Code Playgroud)