我是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