我有大约300百行的文件
TITLE cargas
REMARK 1 File created by GaussView 5.0.9
HETATM 1 O 0 0.957 -0.000 -0.000 O
HETATM 2 H 0 0.000 0.000 0.000 H
HETATM 3 H 0 1.197 0.927 -0.000 H
HETATM 4 O 0 -1.664 -0.019 0.488 O
HETATM 5 H 0 -2.210 0.327 1.194 H
HETATM 6 H 0 -2.260 -0.104 -0.257 H
HETATM 7 O 0 2.189 -2.104 1.321 O
HETATM 8 H 0 1.559 -1.476 0.968 H
HETATM 9 H 0 1.764 -2.955 1.216 H
...
我想要以前的文件的以下形式
TITLE cargas
REMARK 1 File created by GaussView 5.0.9
HETATM 1 O LIG 1 0.957 -0.000 -0.000 O
HETATM 2 H LIG 1 0.000 0.000 0.000 H
HETATM 3 H LIG 1 1.197 0.927 -0.000 H
HETATM 4 O HOH 2 -1.664 -0.019 0.488 O
HETATM 5 H HOH 2 -2.210 0.327 1.194 H
HETATM 6 H HOH 2 -2.260 -0.104 -0.257 H
HETATM 7 O HOH 3 2.189 -2.104 1.321 O
HETATM 8 H HOH 3 1.559 -1.476 0.968 H
HETATM 9 H HOH 3 1.764 -2.955 1.216 H
...
前三行必须写 LIG,其他所有行必须写 HOH。第 5 列的编号从 1 到 100,每个数字三行。
预先感谢您的任何帮助。
答案1
awk '
(NR-2)%3==1 { inc++ }
NR>2 { $4=(inc==1)?"LIG":"HOH"; $5=inc }1' infile
上面的awk
命令由两个条件组成,后跟括号内的操作块,例如condition{ "actions" }
(awk通用语法)。
在awk,美元符号$
是返回其参数的列/字段内容的运算符(注意默认情况下awk考虑制表符/空格序列作为字段分隔符)。
根据上面的解释,异常$0
代表当前行/记录内容以及$1
第一个字段、$2
第二个字段、$3
第三个字段等。
NR 是“到目前为止看到的输入记录总数。”(来自 man awk) 代表 awk 已读取并进行处理的当前行号。
在这种情况下,我们从第 3 行开始每第 4 行递增变量((NR-2)%3==1
跳过前两行);例如,我们确实检查第四行,但从第一行开始,或者做同样的事情,但从第二行开始;通常,我们每隔 4行检查一次,但跳过第一行。inc++
NR-2
(NR-0)%3==1
(NR-1)%3==1
(NR-#)%3==1
#
进行测试,awk '(NR-2)%3==1' infile
看看它打印了哪些行。
在第二个块中,即:NR>2{ $4=(inc==1)?"LIG":"HOH"; $5=inc }
;我们仅更新行号 >2 的行的字段 #4 和 #5 的内容NR>2
(跳过前两行)。
这$4=(inc==1)?"LIG":"HOH"
会将字段 #4 的值设置为“LIG”,直到 varinc
的值仍然=1,否则它将采用“HOH”值;$5=inc
也是取inc
相应的值。
最后1
是awk习惯用法和始终为真条件来打印当前行;看awk 脚本末尾的“1”是什么意思了解详情。
最后,为了保持字段之间的意图,请执行以下操作:
awk -F'( )' '
(NR-2)%3==1 { inc++ }
NR>2 { $9=(inc==1)?"LIG":"HOH"; $14=inc }1' infile
或将第一个 awk 脚本输出传递到awk ... |column -t
.