更改固定格式文件中的选定列

时间:2019-05-08 18:59:14

标签: shell

我有一个以下文件(实际上,它具有更多的列和大量的行)

   0   0 -39  36.093  14.981   3-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
   0   0 -40 336.902  26.500   2-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
   0   0 -41  37.034  15.869   5-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
   0   0 -42  27.538  14.992   1-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181

它是固定格式的文件。在第六列中,我有从1开始到5的数字(格式:I4)。在此特定列中,我需要替换1至20、2-> 21等,而所有其他条目均不受影响。在此示例中,它将产生如下内容:

   0   0 -39  36.093  14.981  22-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
   0   0 -40 336.902  26.500  21-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
   0   0 -41  37.034  15.869  25-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
   0   0 -42  27.538  14.992  20-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181

我进入了论坛,但似乎没有一个解决方案完全符合我的情况。预先表示感谢。

这是该问题的附录。这是原始的单行(请注意空格):

   0   0 -39  36.093  14.981   3-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954  0 287.85 405.71    5.51 287.32 405.17    5.58 1.894 0.53  11.62  90.00 322.65 2 9561     2947   8902   1.67   1 1.000  536346150 -4 0.936   33.55  151.65  91.270 174.170   1

最后建议的解决方案是:

0   0   -39 36.093  14.981  23-0.71520  0.71520-0.16345 0.16345-0.67954-0.67954 0   287.85  405.71  5.51    287.32  405.17  5.58    1.894   0.53    11.62   90.00   322.65  2   9561    2947    8902    1.67    1   1.000   536346150   -4  0.936   33.55   151.65  91.270  174.170 1

2 个答案:

答案 0 :(得分:0)

awk将第六列分为两部分,并由a[1]a[2]表示。后来的第6列被分配了更新的值,其中a[1]增加了20

awk '{split($6,a,"-");$6=a[1]+20"-"a[2]}1' inputfile
0 0 -39 36.093 14.981 23-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
0 0 -40 336.902 26.500 22-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
0 0 -41 37.034 15.869 25-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
0 0 -42 27.538 14.992 21-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181

您可以选择使用OFS="\t"获得更清晰的输出。或使用gsub

   awk  '{split($6,a,"-"); gsub($6,a[1]+20"-"a[2])}1'  input
   0   0 -39  36.093  14.981   23-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
   0   0 -40 336.902  26.500   22-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
   0   0 -41  37.034  15.869   25-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
   0   0 -42  27.538  14.992   21-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181

当输入文件为:

cat input
   0   0 -39  36.093  14.981   3-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
   0   0 -40 336.902  26.500   2-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
   0   0 -41  37.034  15.869   5-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
   0   0 -42  27.538  14.992   1-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181
   0   0 -39  36.093  14.981   3-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954  0 287.85 405.71    5.51 287.32 405.17    5.58 1.894 0.53  11.62  90.00 322.65 2 9561     2947   8902   1.67   1 1.000  536346150 -4 0.936   33.55  151.65  91.270 174.170   1


awk  'NF{split($6,a,"-"); gsub($6,a[1]+20"-"a[2])}1'  input
   0   0 -39  36.093  14.981   23-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954
   0   0 -40 336.902  26.500   22-0.69704 0.69704-0.16844 0.16844-0.69696-0.69696
   0   0 -41  37.034  15.869   25-0.67794 0.67794-0.17335 0.17335-0.71439-0.71439
   0   0 -42  27.538  14.992   21-0.65776 0.65776-0.17833 0.17833-0.73181-0.73181
   0   0 -39  36.093  14.981   23-0.71520 0.71520-0.16345 0.16345-0.67954-0.67954  0 287.85 405.71    5.51 287.32 405.17    5.58 1.894 0.53  11.62  90.00 322.65 2 9561     2947   8902   1.67   1 1.000  536346150 -4 0.936   33.55  151.65  91.270 174.170   1

vimdiff between input and output

答案 1 :(得分:0)

您提到您有一个带有特定输出的固定格式文件。 第6列的格式为I4,它是Fortran格式说明符。

由于我们没有完整的格式,因此我执行了以下操作:

  1. 获取第5列的位置

    $ awk '{match($0,$5); print RSTART+RLENGTH-1; exit}' file
    28
    

这意味着列6从位置29开始,长度为4。 基于此数字,我们现在可以将每个文件分为3部分。长度为28的第一字符串,长度为4的第二字符串以及其余的第三字符串。我们在第二部分中添加20,并以相同的格式进行打印:

$ awk '{p1=substr($0,1,28); p2=substr($0,29,4); p3=substr($0,33)}
       { printf "%s%4d%s\n", p1,p2+20,p3}' file