如何根据输入列表批量更改文件中的文本

如何根据输入列表批量更改文件中的文本

我有大量数据,如下所示

文件1(4600行)

Genome  Gene    Boolean
E15-12  VFG000923   1
E15-13  VFG000924   1
E15-14  VFG000926   1
E15-15  VFG000928   1
E15-16  VFG000930   1
E15-17  VFG000932   1
E15-18  VFG000933   0
E15-19  VFG001448   0
E15-24  VFG013465   1

我想将 col2 中的信息细分为:

文件2(180行)

VFG000923|fepA
VFG000924|fepB
VFG000926|fepD
VFG000928|fepG
VFG000930|entF
VFG000932|entE
VFG000933|entB
VFG001448|kpsD
VFG001450|kpsM
VFG044165|entS

出去

Genome   Gene         Boolean
E15-12  VFG000923|fepA  1
E15-13  VFG000924|fepB  1
E15-14  VFG000926|fepD  1
E15-15  VFG000928|fepG  1
E15-16  VFG000930|entF  1
E15-17  VFG000932|entE  1
E15-18  VFG000933|entB  0
E15-19  VFG001448|kpsD  0
E15-20  VFG001450|kpsM  1

使用@val0x00ff的代码(见评论)

Genome  Gene    Boolean

E15-14 VFG000923|fepA 1

E15-14 VFG000924|fepB 0

E15-14 VFG000926|fepD 1

E15-14 VFG000928|fepG 0

有没有办法用 sed 或 awk 来做到这一点?

答案1

sed

sed '/|/{H;d;};G;s/\([A-Z0-9]*\)\(.*\n\)\1\(|[^[:cntrl:]]*\)/\1\3\2\1\3/;P;d' FILE2 FILE1

应该可以解决问题。这是一个改编这个答案。详细的解释在那里。

答案2

这应该有效:

$ awk 'NR==FNR{k=sub(/\|.*/,$1); a[k]=$1; next} ($2 in a){$2=a[$2]}1' file2 file
Genome Gene Boolean
E15_14 VFG000923|fepA 1
E15_14 VFG000924|fepB 1
E15_14 VFG000926|fepD 0
E15_14 VFG000928|fepG 1
E15_14 VFG000930|entF 0
E15_14 VFG000932|entE 0
E15_14 VFG000933|entB 1
E15_14 VFG001448|kpsD 1
E15_14 VFG001450|kpsM 1
E15_14 VFG044165|entS 0

或者,更容易阅读:

awk 'NR==FNR{
        k=sub(/\|.*/,$1); 
        a[k]=$1; 
        next
    } 
    ($2 in a){
        $2=a[$2]
    }1' file2 file

解释

  • NR==FNR{ }:NR 为当前输入行号,FNR 为当前文件的行号。当读取多个文件时,仅在读取第一个文件时两者才相等。
  • k=sub(/\|.*/,$1);:从该行中删除后面的部分|(由于如上所述,这只发生在第一个文件中NR==FNR)。
  • a[k]=$1;:将第一个文件的第一个字段保存为数组中的值,a其键为基因名称(第一个字段|删除后的所有内容)。
  • next: 跳到下一行。这确保我们在读取第一个文件时不会执行下一个块。
  • ($2 in a):如果第二个字段作为数组中的键存在a(这只会针对第二个文件运行)。
  • $2=a[$2]:将第二个字段设置为存储在afor中的任何内容$2
  • 1:这是 awk 的“打印当前行”的简写。它之所以有效,是因为当 awk 中某项计算结果为 true 时,默认操作是打印当前行。由于1始终为真,因此将打印出来。

答案3

perl -lne '
   @ARGV and %h=(%h, /(.*)\|/ => $_),next;
   !@ARGV and !$a++ and print,next;
   print s//$h{$1}/r if exists $h{(/\h\K(\S+)(?=\h)/)[0]};
' FILE2 FILE1

解释

  • 当读入较小的文件(FILE2)时,我们填充之前数据的%h哈希值,值是整行。keyed|
  • 当读取较大的文件(FILE1)时,我们首先使用以下命令打印它的第一行:!@ARGV and !$a++含义已被清空,并且我们第一次@ARGV看到该变量。$a
  • 在剩下的行中,我们查看是否通过 标识的第二个字段regex /\h\S+\h/来查看该键是否存在于哈希中%h。当发现这是真的时,我们将该字段替换为与该键对应的值。

相关内容