使用 awk 添加和更改文件中的列

使用 awk 添加和更改文件中的列

我有大约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相应的值。

最后1awk习惯用法和始终为真条件来打印当前行;看awk 脚本末尾的“1”是什么意思了解详情。


最后,为了保持字段之间的意图,请执行以下操作:

awk -F'( )' '
    (NR-2)%3==1 { inc++ }
    NR>2        { $9=(inc==1)?"LIG":"HOH"; $14=inc }1' infile

或将第一个 awk 脚本输出传递到awk ... |column -t.

相关内容