我有两个文件,其内容如下:
文件 1:
ATOM 1 N LEU 1 -10.186 -21.276 -0.497 1.00 0.00 PROT
ATOM 2 HT1 LEU 1 -10.773 -22.005 -0.843 1.00 0.00 PROT
ATOM 3 HT2 LEU 1 -9.316 -21.441 -0.958 1.00 0.00 PROT
ATOM 4 HT3 LEU 1 -10.007 -21.389 0.478 1.00 0.00 PROT
ATOM 5 CA LEU 1 -10.642 -19.924 -0.729 1.00 0.00 PROT
ATOM 6 HA LEU 1 -10.092 -19.286 -0.214 1.00 1.00 PROT
ATOM 7 CB LEU 1 -10.604 -19.551 -2.214 1.00 1.00 PROT
ATOM 8 HB1 LEU 1 -11.432 -19.802 -2.731 1.00 1.00 PROT
ATOM 9 HB2 LEU 1 -9.764 -19.989 -2.566 1.00 1.00 PROT
ATOM 10 CG LEU 1 -10.447 -17.969 -2.340 1.00 1.00 PROT
文件 2:
ATOM 1 N LEU 1 -10.186 -21.276 -0.497 1.00 2.00 PROT
ATOM 2 HT1 LEU 1 -10.773 -22.005 -0.843 1.00 4.00 PROT
ATOM 3 HT2 LEU 1 -9.316 -21.441 -0.958 5.00 4.00 PROT
ATOM 4 HT3 LEU 1 -10.007 -21.389 0.478 1.00 4.00 PROT
ATOM 5 CA LEU 1 -10.642 -19.924 -0.729 1.00 3.00 PROT
ATOM 6 HA LEU 1 -10.092 -19.286 -0.214 1.00 4.00 PROT
ATOM 7 CB LEU 1 -10.604 -19.551 -2.214 1.00 3.00 PROT
ATOM 8 HB1 LEU 1 -11.432 -19.802 -2.731 1.00 4.00 PROT
ATOM 9 HB2 LEU 1 -9.764 -19.989 -2.566 1.00 4.00 PROT
ATOM 10 CG LEUUUU 1 -10.447 -17.969 -2.340 1.00 3.00 PROT
所需的输出文件为:
ATOM 1 N LEU 1 -10.186 -21.276 -0.497 1.00 0.00 PROT
ATOM 2 HT1 LEU 1 -10.773 -22.005 -0.843 1.00 0.00 PROT
ATOM 3 HT2 LEU 1 -9.316 -21.441 -0.958 5.00 0.00 PROT
ATOM 4 HT3 LEU 1 -10.007 -21.389 0.478 1.00 0.00 PROT
ATOM 5 CA LEU 1 -10.642 -19.924 -0.729 1.00 0.00 PROT
ATOM 6 HA LEU 1 -10.092 -19.286 -0.214 1.00 1.00 PROT
ATOM 7 CB LEU 1 -10.604 -19.551 -2.214 1.00 1.00 PROT
ATOM 8 HB1 LEU 1 -11.432 -19.802 -2.731 1.00 1.00 PROT
ATOM 9 HB2 LEU 1 -9.764 -19.989 -2.566 1.00 1.00 PROT
ATOM 10 CG LEUUUU 1 -10.447 -17.969 -2.340 1.00 1.00 PROT
我想用文件1中第10列的内容替换文件2中第10列的内容
我的第一次尝试是:
awk -v OFS="\t" 'FNR==NR{a[NR]=$10;next}{$10=a[FNR]}1' file1 file2
但是我得到的选项卡式文件,以及我用来读取它的程序,并不能以选项卡式形式读取它。
然后,我尝试:
awk 'FNR==NR{a[NR]=$10;next}{$10=a[FNR]}1' file1 file2
并且程序也没有读取它。
所以...我需要保留原来的间距。
有什么建议吗?
答案1
这很大程度上受到了 Ed Morton 的回答的启发https://stackoverflow.com/questions/22203066/column-replacement-with-awk-with-retaining-the-format
使用 GNU awk (gawk) 您可以运行:gawk -f my.awk file2.txt file1.txt,其中 my.awk 为:
NR==FNR { pdb[NR]=$0; next }
{
split(pdb[FNR],flds,FS,seps)
flds[10]=$10
for (i=1;i in flds;i++)
printf "%s%s", flds[i], seps[i]
print ""
}
答案2
解决方案:
awk -v FIELDWIDTHS="61 1:4 1:10" 'FNR==NR{a[NR]=$2;next}{$2=a[FNR]}1' file1 file2
解决方案的过程:
由于 awk 删除了所有空格字符,只留下一个,所以我想到了一种方法,如何包含这些空格,并为fields
awk 中命名的列定义固定宽度。下面是FIELDWIDTHS
选项,如GNU Awk 用户指南手动的:
将输入记录拆分为固定宽度的字段是通过将包含空格分隔的数字的字符串分配给内置变量 FIELDWIDTHS 来指定的。每个数字指定字段的宽度,包括字段之间的列。
所以一开始我想到:awk -v FIELDWIDTHS="9 3 4 8 6 8 9 8 6 10 4" 'FNR==NR{a[NR]=$10;next}{$10=a[FNR]}1' file1 file2
但是输出会在从第二个字段开始的所有字段前面添加一个空格(NewField 字符)。所以我尝试跳过一个字符,并在除:1
第一个字段定义之外的所有字段前面添加,但这并没有达到我想要的效果 - 实际上它让事情变得更糟。
但是由于只有一个指定字段需要编辑,我想为什么不将文件分成三个字段,所以我想到了:
awk -v FIELDWIDTHS="62 4 10" 'FNR==NR{a[NR]=$2;next}{$2=a[FNR]}1' file1 file2
但是又有那些多余的空格字符。所以我从第一个字段的长度中减去 1,并用于1:
跳过以下字段的一个字符。
这似乎awk但给出了所需的输出;)
PS:测试时我使用(图形差异应用程序)将输出(通过添加到命令末尾meld
写入 file3)与 file2 进行比较。> file3