我在使用 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。
有人可以帮忙吗? 提前谢谢。
答案 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