来自不同行的 awk

luc*_*ian 5 grep awk text-processing

我正在尝试从不断更新的文件中提取一些数据,并且我已经弄清楚如何使用 grep 过滤两个字符串。输出如下:

!    total energy              =   -9744.24963670 Ry
     convergence has been achieved in 188 iterations
!    total energy              =   -9744.30001681 Ry
     convergence has been achieved in 140 iterations
!    total energy              =   -9744.33953891 Ry
     convergence has been achieved in 155 iterations
!    total energy              =   -9744.36584201 Ry
     convergence has been achieved in 164 iterations
!    total energy              =   -9744.37925372 Ry
     convergence has been achieved in 154 iterations
!    total energy              =   -9744.39185493 Ry
     convergence has been achieved in 153 iterations
!    total energy              =   -9744.39836617 Ry
     convergence has been achieved in 160 iterations
Run Code Online (Sandbox Code Playgroud)

现在我想做的是从这些行中提取数字,如下所示:从以 ​​! 开头的行中提取数字。我想要第 5 列中的数字,从 grep 输出的下一行开始,我想要第 6 列中的数字。接下来,我希望将这些数字作为两个独立的列写入单独的文件中,如下所示:

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201
Run Code Online (Sandbox Code Playgroud)

我正在考虑使用 awk 的方法,循环遍历所有这些 grep 结果,然后查看奇数行并打印第 5 列,然后查看偶数行打印第 6 列。但我不知道该怎么做。

我尝试将各个结果分别提取到变量中:

var1=$(grep '!' input.file | awk '{print $5}')
Run Code Online (Sandbox Code Playgroud)

var2=$(grep 'convergence has been achieved' input.file | awk '{print $6}')
Run Code Online (Sandbox Code Playgroud)

然后我尝试将它们写入文件:

echo $var1 $var2 > data.dat
Run Code Online (Sandbox Code Playgroud)

然而结果并不如预期:

188                                                                                                                                                                                             
140
155
164
154
153
160 -9744.24963670
-9744.30001681
-9744.33953891
-9744.36584201
-9744.37925372
-9744.39185493
-9744.39836617
Run Code Online (Sandbox Code Playgroud)

我不知道如何将它们写成我上面提到的形式。另外,由于文件不断更新,我想象这段代码与 while 循环直到和结束条件结合在一起(我知道如何执行最后一部分)

我希望我解释清楚了!

Rom*_*est 5

awk解决方案:

awk 'v && NR==n{ print $6,v > "result.txt" }/^!/{ v=$5; n=NR+1 }' file
Run Code Online (Sandbox Code Playgroud)
  • <condition1> { <statement> ... }<condition2>{ <statement> ... }- 相应语句的条件将被连续评估

  • /^!/{ v=$5; n=NR+1 }- 遇到以以下开头的行时!- 捕获第 5 个字段值$5并计划下一个行号NR+1(分配给变量n

  • v && NR==n- 如果我们有第一个关键数字v并且当前记录编号NR是所需的“下一行编号” n - 将值打印到文件中result.txt


文件result.txt内容:

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201
154 -9744.37925372
153 -9744.39185493
160 -9744.39836617
Run Code Online (Sandbox Code Playgroud)

  • 太感谢了!这很完美!您介意解释一下解决方案吗?我喜欢尽可能使用 awk,但我发现在这种情况下很难理解语法! (2认同)