我编写了一awk段代码test.awk,内容如下:
#!/bin/awk -f
BEGIN{}
{
for(i=1;i<=NF;i++){
if($i=="celldm(1)="){a=$(NF=i+1);print "a="a}
else if($i=="celldm(2)="){b=$(NF=i+1);print "b="b}
else if($i=="celldm(3)="){c=$(NF=i+1);print "c="c}
else if($i=="celldm(4)="){d=$(NF=i+1);print "d="d}
}
}
END{}
处理的目标文本tmpfile, 内容如下:
system
ibrav= 12 celldm(1)= 10.38828296 celldm(2)= 0.69047339
celldm(3)= 4.44037202
celldm(4)= -0.3452367
nat= 22, ntyp=4
运行 ./test.awk tmpfile后,结果如下:
a=10.38828296
c=4.44037202
d=-0.3452367
请问,为何没有打印b?怎么改,才能打印b? 谢谢各位!
yanyongkg 于 2011-04-25 22:33:43发表:
[i=s] 本帖最后由 yanyongkg 于 2011-4-25 22:42 编辑 [/i]
原因如下
罗嗦一下把整个执行过程写一写:
1。读取第一行,for循环完成,不符合条件,没有执行if后面{}里的内容
2。读取第二行:
ibrav= 12 celldm(1)= 10.38828296 celldm(2)= 0.69047339
对应的$1为ibrav=,$2为12,$3为celldm(1)=,$4为10.38828296,$5为celldm(2)=,$6为0.69047339
i初始值为1,NF初值为6的,for循环到i为3时,"$3"=="celldm(1)="成立,执行后面的a=$(NF=i+1);print "a="a ,此句意思a变量为$4而不是把把4赋值给a,打印出a=10.38828296
问题就出在NF=i+1,这样会把awk的内建变量NF赋值为4了
i为3循环完,然后for循环到i为4就是最后一次循环了,因为i<=NF,所以条件都不符合,跳出。
awk第二行处理完毕。
3。读取第三行:
celldm(3)= 4.44037202
对应$1为celldm(3)=,$2为4.44037202
读取第三行时awk有个动作会把NF又初始为2,这里NF不是刚才的读完第二行的值4,这两只有两个字段看不出,你可以把第二行改为a b c d e f g celldm(3)= 4.44037202,这样的NF会是9,这里可以证明awk读取行是会初始化NF(如果NF为4的话celldm(3)是匹配不到的)。
4。读取第4行,第5行,你懂的。
正解:把a=$(NF=i+1)改成a=$(nu=i+1)或a=$(i+1)
此处nu变量是随便取的,只要不用awk的内建变量NF就行,当然这个nu变量有点多余,用a=$(i+1)就可以了
yanyongkg 于 2011-04-22 09:48:38发表:
没人反对或认同2楼及3楼的解答?
yanyongkg 于 2011-04-19 18:03:40发表:
[i=s] 本帖最后由 yanyongkg 于 2011-4-25 21:56 编辑 [/i]
此处为误解,现已自行删除。
正解在4楼
yanyongkg 于 2011-04-18 01:16:57发表:
[i=s] 本帖最后由 yanyongkg 于 2011-4-25 21:56 编辑 [/i]
试了一下,确实如你所说的b打印不出。
原因可能是这样的,个人意见,仅供参考。
说说awk处理过程
步骤1:读取文件的第一行
步骤2:将读取的这一行按照分隔符分割成数个字段,默认分隔符为空白键(我理解这的空白符也包括TAB,不知正解与否)。将第一个字段放入到变量$1中,第二个放到$2中,$0表示整行
步骤3:根据条件判断来决定是否执行后面的动作
步骤4:读取文件第二行及后面所有行,重复步骤1至步骤3
test.awk来处理tmpfile文件的过程大概是这样的(个人理解不一定说法妥当,仅供参考):
自处为误解,现已自行删除。