替换固定宽度文件中的单个条目

时间:2017-05-21 21:17:40

标签: bash sed echo cut

我有一个固定宽度的数据文件,如下所示:

ATOM   6181  H4  BGLC    2      -6.078 -11.556   0.599  1.00  0.00
ATOM   6182  O4  BGLC    2      -5.410 -10.816   2.307  1.00  7.76
ATOM   6183  C6  BGLC    2      -8.313 -11.233   1.955  1.00  8.41
ATOM   6184  H61 BGLC    2      -9.308 -11.734   2.225  1.00  0.00
ATOM   6185  H62 BGLC    2      -8.302 -10.340   2.573  1.00  0.00
ATOM   6186  O6  BGLC    2      -8.412 -11.033   0.547  1.00  8.44
ATOM   6187  HO6 BGLC    2      -7.623 -10.829   0.055  1.00  0.00
ATOM   6188  C1  BGLC    3      -4.821  -9.797   1.481  1.00  7.45
ATOM   6189  H1  BGLC    3      -5.419  -9.613   0.596  1.00  0.00

我正在尝试将最后两列替换为其他变量chargeradius。我尝试使用cut来挑选该行的前54个字符(前8列),然后使用echo将chargeradius添加到最后,如下所示:

newline=$(echo $(echo $pqratomline | cut -c 1-54) $charge $radius)

其中pqratomline是一个等于文件中特定行的字符串。但是,echo会消除额外的空白,从而抛出固定宽度的列。

有没有人建议如何在不使用echo的情况下执行此操作,或者保持echo不会删除额外的空格?

修改 我希望得到这样的东西(只显示前几行):

ATOM   6181  H4  BGLC    2      -6.078 -11.556   0.599  0.0900  1.3400
ATOM   6182  O4  BGLC    2      -5.410 -10.816   2.307 -0.6500  1.7650
相反,我得到了:

ATOM 6181 H4 BGLC 2 -6.078 -11.556 0.599 0.0900 1.3400
ATOM 6182 O4 BGLC 2 -5.410 -10.816 2.307 -0.6500 1.7650

3 个答案:

答案 0 :(得分:1)

作为替代方案,您可以使用printf代替echo,因为printf具有更好的行为,您还可以调整每个打印变量的宽度:

$ echo "$a"
ATOM   6179  HO3 BGLC    2      -3.020 -13.471   0.981  1.00  0.00

$ charge="2.22";radius="2.22"

$ newline=$(printf '%s%6s%6s\n' "$(echo "$a" | cut -c 1-54)" "$charge" "$radius");echo "$newline"
ATOM   6179  HO3 BGLC    2      -3.020 -13.471   0.981  2.22  2.22

%6s中的printf格式指示要以6个字符宽度打印的变量。

类似地:

$ echo "$a"
ATOM   6179  HO3 BGLC    2      -3.020 -13.471   0.981  1.00  0.00

$ charge="0.0900";radius="1.3400"

$ newline=$(printf '%s%12s%12s\n' "$(echo "$a" | cut -c 1-54)" "$charge" "$radius");echo "$newline"
ATOM   6179  HO3 BGLC    2      -3.020 -13.471   0.981      0.0900      1.3400

您可以根据需要调整新字段宽度(%12s以上)的值。

答案 1 :(得分:0)

假设您的费用和半径变量不包含反向引用或/ s或其他任何可能关心的内容:

$ charge=7
$ radius=2.5

$ sed 's/[^ ]*\( *\)[^ ]*$/'"$charge"'\1'"$radius"'/' file
ATOM   6181  H4  BGLC    2      -6.078 -11.556   0.599  7  2.5
ATOM   6182  O4  BGLC    2      -5.410 -10.816   2.307  7  2.5

请注意,您发布的预期输出不会遵循与输入相同的固定宽度布局(它会保留最后2个字段之间的间距,但会扩展每个字段占用的空间),因此上述解决方案也不会。

答案 2 :(得分:-1)

awk的一个问题是,除非你特别注意准备输出格式,否则它会删除空格,从而破坏你的固定宽度间距。

awk -v charge="$charge" -v radius="$radius" '
  {
    printf "%54s%8.4f%8.4f\n", substr($0,1,54), charge, radius
  }
' input.txt

这使用awk的-v选项将环境变量插入到awk脚本中。

当然,您可以在bash中执行此操作并使用参数扩展来去除您不想要的行的部分...

while read line; do

  lhs=${line:0:54}    # The first 54 characters...
  rhs=${line:54}      # in case you need these for later...

  printf '%s%8.4f%8.4f\n' "$lhs" "$charge" "$radius"

done < input.txt