根据另一个文件中的值替换变量



我是awk的新手,希望在文件2中的转换中替换文件1中的IID。这两个文件都是txt文件。

我有一个文件(文件1)它看起来像这样(只显示前两列),有2060行:
FID IID
1   RQ00001-2
2   RQ00002-0
3   RQ00004-9
4   RQ00005-4   
5   RQ00006-5

我有另一个文件显示iid到另一种格式的转换。这个文件看起来像这样:

id Id
468768 RQ00001-2
468769 RQ00006-5
468770 RQ00005-4
468771 RQ00002-0
468772 RQ00004-9

所以我想替换IIDid使用文件2作为转换。所以文件1应该是这样的:

FID IID
1 468768    
2 468771    
3 468772    
4 468770        
5 468769    

所以我本质上想用文件2中的id替换IID使用文件2作为转换。

我知道我可以用awk做到这一点,但我不确定如何。如有任何帮助,不胜感激。

说明:OP最初的问题包括:

awk 'FNR==NR{a[$1]=$2;next} {print $1,$1 in a?a[$1]:$2}' OFS="t" Input_file2 Input_file1
But I have no idea what this means    ^ and I don't think it's applicable for my problem. 

$1 in a ? a[$1] : $2是awk三元操作符。

在这种情况下,它读:如果$1 in a,则输出a[$1],否则输出$2

在这个特殊情况下,如果$1(第二个文件的第一个字段)是a[]数组中的索引,则打印a[$1]数组项的内容,否则打印$2(第二个文件的第二个字段)的内容;换句话说,三元运算符决定是保留当前字段#2的值,还是将其替换为数组中的对应值。

话虽如此,我认为目前的awk代码有问题…


假设:

  • 如果file #1 / field #2匹配file #2 / field #2,则…
  • file #2 / field #1
  • 中的值替换file #1 / field #2

修改awk的一个想法:

awk -v OFS="t" '                          # just my personal preference to list variables first; OP can leave after script and before files
# process 1st input file
FNR==NR { if ( FNR>1 )                     # skip 1st line "id Id"
a[$2]=$1                      # 2nd file: 2nd field is index, 1st field is replacement value
next
}
# process 2nd input file
{ print $1,$2 in a ? a[$2] : $2 }  # if 2nd field is an index in array a[] then replace it with said array value else keep current 2nd field 
' Input_file2 Input_file1
# eliminating comments and pesky white space for a 'compact' one-liner:
awk -v OFS="t" 'FNR==NR {if(FNR>1)a[$2]=$1;next}{print $1,$2 in a?a[$2]:$2}' Input_file2 Input_file1

这两个都生成:

FID     IID
1       468768
2       468771
3       468772
4       468770
5       468769

指出:

  • OP提到想要替换文件#1中的值;OP需要将这个awk脚本的输出捕获到另一个(临时)文件中,然后用这个新的(临时)文件覆盖原始文件;由OP决定是否应该首先创建文件#1的备份副本
  • OP提到文件#1有超过2列;假设列的数量可能是"大"和/或动态的,OP可以对代码进行以下更改…

修改代码以替换file #1 / field #2,然后打印行:

# change from:
{ print $1,$2 in a ? a[$2] : $2 }
# change to:
{ $2 = $2 in a ? a[$2] : $2; print }   # overwrite value in field #2 in current line and then print current line