Search code examples
bashsedechocut

Replacing Individual Entries in Fixed Width File


I have a fixed-width data file that looks like this:

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

I am trying to replace the last two columns with other variables charge and radius. I've tried using cut to pick out the first 54 characters of the line (the first 8 columns) and then using echo to tack charge and radius onto the end, like this:

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

where pqratomline is a string equal to a particular line in the file. However, echo strips out the extra whitespace, which throws off the fixed width columns.

Does anyone have any recommendations on how to do this without using echo, or to keep echo from removing that extra whitespace?

EDIT: I'd like to get something that looks like this (just showing the first few lines):

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

Instead, I'm getting:

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

Solution

  • As an alternative you can use printf instead of echo since printf has much better behavior and you can also adjust the width of each printed variable:

    $ 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
    

    The %6s format in printf dictates variable to be printed with 6 chars width.

    Similarly:

    $ 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
    

    You can adjust the value of the new fields width (%12s above) according to your needs.