我有一个列字段类型标准的文件(其中字符1
到6
对应于field 1
,7
到11
到field 2
,依此类推)。
关键属性包括:
- 每行长度为
80
个字符 field 2
到field N
中的文本总是right
在字段内对齐
我有一个文件像:
REMARK 1
HETATM 1
HETATM 5
HETATM 6
HETATM 7
HETATM 9
HETATM 12
HETATM 15
HETATM 19
HETATM 23
HETATM 27
HETATM 30
HETATM 34
HETATM 38
END
对于HETATM
记录。。。前六个原子等于那根弦的线。。。我想将第二个字段中的数字(字符7
到11
)替换为条目编号,从1
开始。
即,我希望输出显示为:
REMARK 1
HETATM 1
HETATM 2
HETATM 3
HETATM 4
HETATM 5
HETATM 6
HETATM 7
HETATM 8
HETATM 9
HETATM 10
HETATM 11
HETATM 12
HETATM 13
END
目前,我最简洁的解决方案(使用临时文件进行测试,以避免弄乱我的原始文件)是:
#!/bin/bash
f=file.pdb
fTmp=${f}.tmp
cp $f $fTmp
for ((l=1; l<$( wc -l $fTmp | awk '{print $1}' ); l++)); do
sed -i "$((l + 1))"'s#(HETATM)[ 0-9]{5}#1'"$( printf '%5s' $l )"'#g' $fTmp
done
cat $fTmp
rm $fTmp
删除临时文件行李,这变成:
f=file.pdb
for ((l=1; l<$( wc -l $f | awk '{print $1}' ); l++)); do
sed -i "$((l + 1))"'s#(HETATM)[ 0-9]{5}#1'"$( printf '%5s' $l )"'#g' $f
done
似乎应该有一些方法可以在sed
中使用行号来创建一个更简短的解决方案——也许是一个sed -i
命令。假设这是可能的,唯一的复杂性是需要一点算术运算——应该设置为1
的第一个匹配总是发生在第二行。
我希望有一个sed
解决方案。我对使用awk
犹豫不决,因为考虑到空格填充很重要,并且需要内联编辑,似乎sed
是更好的选择。
请注意,一旦我有了一个经验证有效的改进解决方案,我就会扔掉*.tmp
文件的东西,直接对目标文件进行操作,因此一个sed -i
命令就有可能完成这项工作。
如果你有GNU awk,你可以指定你的输入在固定宽度的字段中。例如,
awk -v OFS='' -v FIELDWIDTHS='6 5 6 6 6 6 6' '
/^HETATM/{ $2 = sprintf("%5d",++count) };1' file.pdb
这将把宽度为5的字段2编辑为一个递增的数字。