【问题标题】:Replace variables based upon a value in another file根据另一个文件中的值替换变量
【发布时间】:2021-12-04 09:57:16
【问题描述】:

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

我有一个文件 (file 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

所以我想将文件 1 中的 IID 替换为 id,使用文件 2 作为转换。所以文件 1 应该是这样的:

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

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

我知道我可以用 awk 做到这一点,但我不知道怎么做。任何帮助将不胜感激。

【问题讨论】:

  • 感谢您的回复。现在已经完成了。我的第一个文件大约有 2060 行。

标签: bash awk grep


【解决方案1】:

注意: 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] : $2awk ternary operator

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

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

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


假设:

  • 如果file #1 / field #2 匹配file #2 / field #2 那么...
  • file #1 / field #2 替换为file #2 / field #1 中的值

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

【讨论】:

  • 非常感谢您的回复。当我的两个文件长度不同时,这可以工作吗?例如,文件 1 是 2060,文件 2 是 4224。文件 2 本质上具有额外的 ID。
  • 行数应该不是问题;由于此 awk 代码不会覆盖原始文件,我建议您针对文件运行代码并验证结果输出(如有疑问,请尝试!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2020-01-08
  • 2023-04-09
  • 1970-01-01
  • 2023-01-26
  • 2015-10-03
  • 2021-02-22
相关资源
最近更新 更多