如何使用grep和awk提取特定值?

时间:2017-07-22 04:07:39

标签: linux bash awk grep

我在使用 grep awk 在.txt文件中提取特定值时遇到问题。 我在下面显示.txt文件的摘录: “ -

 bravais-lattice index     =            2
 lattice parameter (alat)  =      10.0000  a.u.
 unit-cell volume          =     250.0000 (a.u.)^3
 number of atoms/cell      =            2
 number of atomic types    =            1
 number of electrons       =        28.00
 number of Kohn-Sham states=           18
 kinetic-energy cutoff     =      60.0000  Ry
 charge density cutoff     =     300.0000  Ry
 convergence threshold     =      1.0E-09
 mixing beta               =       0.7000"

我还定义了一些变量:ELEMENT和lat。 我想提取等于250.00的“单元格体积”值。 我尝试使用以下方法使用grep和awk提取值:

volume=`grep "unit-cell volume" ./latt.10/$ELEMENT.scf.latt_$lat.out | awk '{printf "%15.12f\n",$5}'`

但是,当我运行bash文件时,我总是得到00.000000,而不是正确的值250.00。

有人可以帮忙吗? 提前谢谢。

3 个答案:

答案 0 :(得分:3)

awk '{printf "%15.12f\n",$5}'

您要求awk打印出该行的第五个字段($5)。

 unit-cell volume          =     250.0000 (a.u.)^3
 1         2               3     4        5

第五个字段是(a.u.)^3,然后您要求awk通过%f格式代码解释为数字。它不是一个数字(或者实际上,不是以数字开头),并且当要求awk将非数字字符串视为数字时,它使用0代替。因此它打印0。

解决方案:改为使用$4

顺便说一句,您可以通过使用awk本身选择行来跳过调用grep,例如

awk /^ unit-cell/ {...}

/^ unit-cell/是一个匹配" unit-cell"的正则表达式。 (在前面有一个前导空格)。如果您有其他以unit-cell开头并且您不想选择的行,请根据需要进行调整。

答案 1 :(得分:1)

当你使用awk时,你永远不需要grep,因为awk可以做任何有用的事情,grep可以做。听起来这就是你所需要的:

$ awk -F'=' '/unit-cell volume/{printf "%.2f\n",$2}' file
250.00

上述方法有效,因为当FS为=表示$2<spaces>250.000 (a.u.)^3时,当要求awk将字符串转换为数字时,它会删除前导空格和数字之后的任何内容部分,以便250.000%.2f转换为数字。

在您发布的脚本$5失败了,因为第5个以空格分隔的字段位于:

    $1         $2    $3      $4         $5
<unit-cell> <volume> <=> <250.0000> <(a.u.)^3>

(a.u.)^3 - 您可以刚刚添加print $5来查看。

答案 2 :(得分:0)

由于您正在处理键值可能在其中具有可变空间量的键值对,因此您需要为要处理的每个记录分别调整该字段编号($ 4,$ 5等),除非您设置该字段分隔符(FS)适当地FS=" *= *"。然后,密钥将始终为1美元,价值为2美元。

然后使用split将值和单位部分相互分开。

此外,您可以通过在awk中为grep操作定义模式(或条件/unit-cell volume/)来放宽print

$ awk 'BEGIN{FS=" *= *"} /unit-cell volume/{split($2,a," +");print a[1]}' file
250.0000

说明:

$ awk '
BEGIN { FS=" *= *" }   # set appropriate field separator
/unit-cell volume/ {   # pattern or condition
    split($2,a," +")   # split value part to value and possible unit parts
    print a[1]         # output value part
}' file
相关问题