Sed模式匹配,使用替换字符串中行号的偏移



我有一个列字段类型标准的文件(其中字符16对应于field 1711field 2,依此类推)。

关键属性包括:

  • 每行长度为80个字符
  • field 2field 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记录。。。前六个原子等于那根弦的线。。。我想将第二个字段中的数字(字符711)替换为条目编号,从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编辑为一个递增的数字。

相关内容

  • 没有找到相关文章

最新更新