Replace 用awk替换列,保留格式

Replace 用awk替换列,保留格式,replace,awk,format,Replace,Awk,Format,这是文件a.pdb: 这是文件a.xyz: 我想用a.xyz列替换a.pdb的6、7和第8列。一旦被替换,我需要维护a.pdb的制表符/空格/列 我试过: awk 'NR==FNR {fld1[NR]=$1; fld2[NR]=$2; fld3[NR]=$3; next} {$6=fld1[FNR]; $7=fld2[FNR]; $8=fld3[FNR]}1' a.xyz a.pdb 但是它没有保留格式。不是通用的解决方案,但在这种特殊情况下,这可能适用于: awk 'NR==FNR{for

这是文件a.pdb:

这是文件a.xyz:

我想用a.xyz列替换a.pdb的6、7和第8列。一旦被替换,我需要维护a.pdb的制表符/空格/列

我试过:

awk 'NR==FNR {fld1[NR]=$1; fld2[NR]=$2; fld3[NR]=$3; next} {$6=fld1[FNR]; $7=fld2[FNR]; $8=fld3[FNR]}1' a.xyz a.pdb 

但是它没有保留格式。

不是通用的解决方案,但在这种特殊情况下,这可能适用于:

awk 'NR==FNR{for(i=6; i<=8; i++) A[FNR,i]=$(i-5); next} {for(i=6; i<=8; i++) sub($i,A[FNR,i])}1' file2 file1
-在OP的原始解决方案中更改它:

awk 'NR==FNR {fld1[NR]=$1; fld2[NR]=$2; fld3[NR]=$3; next} {sub($6,fld1[FNR]); sub($7,fld2[FNR]); sub($8,fld3[FNR])}1' file file1
与前两个建议具有相同的限制

因此,1、2和4使用sub替换,这不是防水的解决方案,因为早期的字段可能会干扰,并且它使用正则表达式而不是字符串,因此正则表达式点恰好与实际点匹配,但使用此特定输入,它可能会平移

3号可能是一种更简单的方法

-编辑- 我认为在给定的输入条件下,这会起作用:

awk 'NR==FNR{A[FNR]=$1 "  " $2 " " $3; next} {print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))}' p=32  file2 file1
但我认为需要printf或sprint格式这样的东西才能使它变得简单。 所以,也许是这样的:

awk 'NR==FNR{A[FNR]=sprintf("%7.3f %7.3f %8.4f", $1, $2, $3); next} {print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))}' p=31 file2 file1
或者不在一行上:

awk '
  NR==FNR {
    A[FNR]=sprintf("%7.3f %7.3f %8.4f", $1, $2, $3)
    next
  }
  {
    print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))
  }
' p=31 file2 file1

不是一个通用的解决方案,但在这种特殊情况下,这可能适用于:

awk 'NR==FNR{for(i=6; i<=8; i++) A[FNR,i]=$(i-5); next} {for(i=6; i<=8; i++) sub($i,A[FNR,i])}1' file2 file1
-在OP的原始解决方案中更改它:

awk 'NR==FNR {fld1[NR]=$1; fld2[NR]=$2; fld3[NR]=$3; next} {sub($6,fld1[FNR]); sub($7,fld2[FNR]); sub($8,fld3[FNR])}1' file file1
与前两个建议具有相同的限制

因此,1、2和4使用sub替换,这不是防水的解决方案,因为早期的字段可能会干扰,并且它使用正则表达式而不是字符串,因此正则表达式点恰好与实际点匹配,但使用此特定输入,它可能会平移

3号可能是一种更简单的方法

-编辑- 我认为在给定的输入条件下,这会起作用:

awk 'NR==FNR{A[FNR]=$1 "  " $2 " " $3; next} {print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))}' p=32  file2 file1
但我认为需要printf或sprint格式这样的东西才能使它变得简单。 所以,也许是这样的:

awk 'NR==FNR{A[FNR]=sprintf("%7.3f %7.3f %8.4f", $1, $2, $3); next} {print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))}' p=31 file2 file1
或者不在一行上:

awk '
  NR==FNR {
    A[FNR]=sprintf("%7.3f %7.3f %8.4f", $1, $2, $3)
    next
  }
  {
    print substr($0,1,p) A[FNR] substr($0,p+length(A[FNR]))
  }
' p=31 file2 file1
你可以试试这个

paste -d' '  test4 test5 |awk '{print $1,$2,$3,$4,$5,$12,$13,$14,$9,$10,$11}'
你可以试试这个

paste -d' '  test4 test5 |awk '{print $1,$2,$3,$4,$5,$12,$13,$14,$9,$10,$11}'

这正是GNU awk中split的第四个arg的发明目的:

gawk '
NR==FNR { pdb[NR]=$0; next }
{
    split(pdb[FNR],flds,FS,seps)
    flds[6]=$1
    flds[7]=$2
    flds[8]=$3
    for (i=1;i in flds;i++)
        printf "%s%s", flds[i], seps[i]
    print ""
}
' a.pdb a.xyz

ATOM      1  N   ARG     1       16.388   -5.760   -23.332  1.00  0.00           N
ATOM      2  H1  ARG     1       17.226   -5.608   -23.768  1.00  0.00           H
ATOM      3  H2  ARG     1       15.760   -5.238   -23.831  1.00  0.00           H
ATOM      4  H3  ARG     1       17.921   -5.926   -26.697  1.00  0.00           H

这正是GNU awk中split的第四个arg的发明目的:

gawk '
NR==FNR { pdb[NR]=$0; next }
{
    split(pdb[FNR],flds,FS,seps)
    flds[6]=$1
    flds[7]=$2
    flds[8]=$3
    for (i=1;i in flds;i++)
        printf "%s%s", flds[i], seps[i]
    print ""
}
' a.pdb a.xyz

ATOM      1  N   ARG     1       16.388   -5.760   -23.332  1.00  0.00           N
ATOM      2  H1  ARG     1       17.226   -5.608   -23.768  1.00  0.00           H
ATOM      3  H2  ARG     1       15.760   -5.238   -23.831  1.00  0.00           H
ATOM      4  H3  ARG     1       17.921   -5.926   -26.697  1.00  0.00           H


替换算法是什么?一个文件的第一行与另一个文件的第一行内容?行号匹配@fedorquiWell我猜a.pdb是制表符分隔的,而a.xyz是空格分隔的。如果将这两个选项都设置为tab sep呢?我尝试使用cat a.xyz | column-t选项,但在awk替换后,a.pdb的格式变松了。它不会保持列号对齐。是否使用BEGIN{FS=OFS=\t}解释FS和OFS?祝你好运,替换算法是什么?一个文件的第一行与另一个文件的第一行内容?行号匹配@fedorquiWell我猜a.pdb是制表符分隔的,而a.xyz是空格分隔的。如果将这两个选项都设置为tab sep呢?我尝试使用cat a.xyz | column-t选项,但在awk替换后,a.pdb的格式变松了。它不会保持列号对齐。是否使用BEGIN{FS=OFS=\t}解释FS和OFS?祝你好运。注意OPs语法很好,他只是要求保留格式。@fedorqui,好的观点,我在其他建议中添加了一个改编。除了第6-8列中的一个小移位外,它是有效的。a.pdb中的第6-8列左对齐。小数点应该出现在第35、43和51列中。注意OPs语法很好,他只是要求保留格式。@fedorqui,好的,我在其他建议中添加了一个修改。除了在第6-8列中有一个小的变化外,它是有效的。a.pdb中的第6-8列左对齐。小数点应该出现在第35、43和51列中。做得很好。我想利用我的投票来回答一个问题:。在for循环中,您选择在flds中使用i,而不是捕获分割函数返回值,并且无论采用哪种方式都没有什么大不了的,它只是少了一个全局变量,您不必担心填充,也不必担心与脚本中其他地方同名的变量发生冲突。显然,在这么小的脚本中没有问题。注意,这种方法只有在数组索引中没有洞的情况下才有效。明白了!谢谢你的解释+1正式给予!顺便说一句,每个人的桌子上都需要一本awk食谱!眨眼眨眼是的,我已经考虑过了。类似于Chris Johnson的Bash脚本编写方法,但适用于awk。总有一天…+1用于gawk的漂亮功能,Ed。但是小数点不在第35、43和51列。做得很好。我想利用我的投票来回答一个问题:。在for循环中,您选择在flds中使用i,而不是捕获分割函数返回值,并且无论采用哪种方式都没有什么大不了的,它只是少了一个全局变量,您不必担心填充,也不必担心与脚本中其他地方同名的变量发生冲突。显然,在这么小的脚本中没有问题。注意,这种方法只有在数组索引中没有洞的情况下才有效。明白了!谢谢你的解释+1正式给予!顺便说一句,每个人的桌子上都需要一本awk食谱!眨眼眨眼是的,我已经考虑过了。类似于Chris Johnson的Bash脚本编写方法,但是
为了awk。总有一天…+1用于gawk的nice功能,Ed.但小数点不在第35、43和51列中。