编辑文本列

时间:2014-02-17 13:03:06

标签: sed awk grep

我有一个文本文件(前两行是字符间距):

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
ATOM      1  N1  SPINA   3      30.616  29.799  14.979  1.00 20.00      S    N  
ATOM      2  N1  SPINA   3      28.146  28.381  13.950  1.00 20.00      S    N  
ATOM      3  N1  SPINA   3      27.605  28.239  14.037  1.00 20.00      S    N  
ATOM      4  N1  SPINA   3      30.333  29.182  15.464  1.00 20.00      S    N  
ATOM      5  N1  SPINA   3      29.608  29.434  14.333  1.00 20.00      S    N  
ATOM      6  N1  SPINA   3      29.303  29.830  13.317  1.00 20.00      S    N  
ATOM      7  N1  SPINA   3      28.963  31.116  13.472  1.00 20.00      S    N  
ATOM      8  N1  SPINA   3      28.859  28.743  13.828  1.00 20.00      S    N  
ATOM      9  N1  SPINA   3      29.699  30.575  14.564  1.00 20.00      S    N  
ATOM     10  N1  SPINA   3      29.518  29.194  15.301  1.00 20.00      S    N

我想编辑它并使它像:

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
ATOM      1 N001 SPINA   3      30.616  29.799  14.979  1.00 20.00      S    N  
ATOM      2 N002 SPINA   3      28.146  28.381  13.950  1.00 20.00      S    N  
ATOM      3 N003 SPINA   3      27.605  28.239  14.037  1.00 20.00      S    N  
ATOM      4 N004 SPINA   3      30.333  29.182  15.464  1.00 20.00      S    N  
ATOM      5 N005 SPINA   3      29.608  29.434  14.333  1.00 20.00      S    N  
ATOM      6 N006 SPINA   3      29.303  29.830  13.317  1.00 20.00      S    N  
ATOM      7 N007 SPINA   3      28.963  31.116  13.472  1.00 20.00      S    N  
ATOM      8 N008 SPINA   3      28.859  28.743  13.828  1.00 20.00      S    N  
ATOM      9 N009 SPINA   3      29.699  30.575  14.564  1.00 20.00      S    N  
ATOM     10 N010 SPINA   3      29.518  29.194  15.301  1.00 20.00      S    N

每列之间的空格数很重要,原子列表需要达到190(N001-N190)。因此,我想将文件1中的字符13-16(“N1”)替换为(“N001”),并将文件的其余部分保留为原始间距。

4 个答案:

答案 0 :(得分:2)

您不需要10行长的样本输入来演示问题或解决方案:

$ cat file
ATOM      1  N1  SPINA   3
ATOM      2  N1  SPINA   3
ATOM     10  N1  SPINA   3

$ awk '{print substr($0,1,12) sprintf("N%03d",$2) substr($0,17)}' file
ATOM      1 N001 SPINA   3
ATOM      2 N002 SPINA   3
ATOM     10 N010 SPINA   3

我假设我们可以使用$ 2作为第3个字段的数字部分。它似乎按行号顺序递增。使用NR可能是另一种选择。如果这些都不是您想要的,请发布更具代表性的样本输入/输出。

另请注意,任何涉及分配给字段的解决方案(例如$3=...)都会导致awk使用OFS的值作为字段分隔符重新编译该行,因此会更改您的间距。

哦,如果这两个字符间距的初始行确实存在于你的文件中,那就是调整:

$ cat file
         1         2
12345678901234567890123456
ATOM      1  N1  SPINA   3
ATOM      2  N1  SPINA   3
ATOM     10  N1  SPINA   3

$ awk 'NR>2{$0 = substr($0,1,12) sprintf("N%03d",$2) substr($0,17)} 1' file
         1         2
12345678901234567890123456
ATOM      1 N001 SPINA   3
ATOM      2 N002 SPINA   3
ATOM     10 N010 SPINA   3

答案 1 :(得分:1)

尝试:

$ awk '{$3=substr($3,1,1) sprintf("%03d",$2)}1' OFS=\\t file

注意:OFS将是标签

如果您想在Solaris/SunOS系统上尝试此操作,请将awk更改为/usr/xpg4/bin/awk/usr/xpg6/bin/awknawk

<强> - 编辑 -

如果你想用行增加

$ awk '{$3=substr($3,1,1) sprintf("%03d",NR)}1' OFS=\\t file

答案 2 :(得分:1)

这是另一种方式:

awk 'sub(/.$/,sprintf("%03d",NR),$3)' OFS='\t' file

<强>输出:

$ awk 'sub(/.$/,sprintf("%03d",NR),$3)' OFS='\t' file 
ATOM    1       N001    SPINA   3       30.616  29.799  14.979  1.00    20.00   S       N
ATOM    2       N002    SPINA   3       28.146  28.381  13.950  1.00    20.00   S       N
ATOM    3       N003    SPINA   3       27.605  28.239  14.037  1.00    20.00   S       N
ATOM    4       N004    SPINA   3       30.333  29.182  15.464  1.00    20.00   S       N
ATOM    5       N005    SPINA   3       29.608  29.434  14.333  1.00    20.00   S       N
ATOM    6       N006    SPINA   3       29.303  29.830  13.317  1.00    20.00   S       N
ATOM    7       N007    SPINA   3       28.963  31.116  13.472  1.00    20.00   S       N
ATOM    8       N008    SPINA   3       28.859  28.743  13.828  1.00    20.00   S       N
ATOM    9       N009    SPINA   3       29.699  30.575  14.564  1.00    20.00   S       N
ATOM    10      N010    SPINA   3       29.518  29.194  15.301  1.00    20.00   S       N

答案 3 :(得分:1)

如果您对使用纯shell解决它感兴趣,请输入以下代码:

while IFS="\n" read -r line
do     
  n=${line:9:3}
  printf "%sN%03d%s\n" "${line:0:12}" $n "${line:16}"
done < file