如果文件 B 中的行与文件 A 中的多列匹配,则删除文件 A 中的行,将匹配的行放入文件 C 中,并将不匹配的行放入文件 D 中

如果文件 B 中的行与文件 A 中的多列匹配,则删除文件 A 中的行,将匹配的行放入文件 C 中,并将不匹配的行放入文件 D 中

我有 2 个文件 -文件A这是包含 10 多列和大约 15,000 行的主文件,以及文件B,其中包含 4 列和约 1500 行。

我想一次获取每一行文件B,并将这些列与中的相应列相匹配文件A(两个文件之间的顺序不同,但列标题相同)。如果所有 4 列都匹配文件B文件A,然后从中删除整行文件A,并放入一个新文件(文件C)。

我还需要任何不匹配的行文件B被放入一个新文件中(文件D)。

例子:

文件A:

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 4   57497067    na  no  612 612 DonorAR2
54  Baillie2011 X   154790187   TMLHE   no  612 612 DonorAR2
54  Baillie2011 5   159351203   ADRA1B  no  612 612 DonorAR2
54  Baillie2011 13  79259801    na  no  612 612 DonorAR2
54  Baillie2011 8   4452925 CSMD1   no  610 610 DonorAH

文件B:

study_id.x  sample_name chromosome  g_start
Baillie2011 DonorAH 8   4452925
Baillie2011 DonorBC 9   5491376
Baillie2011 DonorAH 8   5829283
Baillie2011 DonorCH 8   5829283

结果:

文件A:

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 4   57497067    na  no  612 612 DonorAR2
54  Baillie2011 X   154790187   TMLHE   no  612 612 DonorAR2
54  Baillie2011 5   159351203   ADRA1B  no  612 612 DonorAR2
54  Baillie2011 13  79259801    na  no  612 612 DonorAR2

文件C:

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 8   4452925 CSMD1   no  610 610 DonorAH

文件D:

study_id.x sample_name chromosome g_start
Baillie2011 DonorBC 9 5491376 
Baillie2011 DonorAH 8 5829283 
Baillie2011 DonorCH 8 5829283

答案1

使用 awk 脚本如下:

NR == FNR {
        strt=1
        }
NR != 1 && FNR ==1 {
        strt=0
        }
strt == 1 {
        fileB[FNR"_"$1$2$3$4]=$0
        }
strt == 0 {
        fileA[$2$9$3$4]=$0
        }
END {
        for (i in fileB) {
                split(i,arry,"_")
                if (fileA[arry[2]] != "") {
                                print fileA[arry[2]] > "fileC"
                                system("sed -i \"/"fileA[arry[2]]"/d\" 
fileA") 
                }
                else {
                                 print fileB[i] > "fileD"
                }
        }

我们首先将每个文件中的行读入两个数组,fileA 和 fileB,并且两者都具有相同的键,即“Baillie2011DonorAH84452925”。我们循环遍历 fileB 数组中的每个条目,并检查 fileA 中是否有相应的条目。如果存在,则通过打印重定向将条目添加到 fileC,并通过 awk 的系统函数执行 sed 命令(注意 - 系统函数带有代码注入风险,因此相应地评估风险)如果没有匹配,则将该行输出到文件 D.

行动:

awk -f awkscriptfile fileB fileA

答案2

用法: ./processing.sh

该脚本不会更改原始文件file_A,而是创建new_file_A.您可以向其中添加几行代码,用于删除原始代码file_A并将其重命名new_file_Afile_A.我可以在代码中添加注释,如果可以的话,你想要什么。

#!/bin/bash

file_a="file_A.txt"
file_b="file_B.txt"
file_c="file_C.txt"
file_d="file_D.txt"

print_to_files () {
    awk -v lines="$1" -v outfile1="$3" -v outfile2="$4" '
        BEGIN {
            cnt = 2;
            split(lines,lines_arr);
        }

        {
            if (NR == 1) {
                print $0 > outfile1;
                print $0 > outfile2;
            } else if (NR == lines_arr[cnt]) {
                print $0 >> outfile1;
                cnt++;
            } else {
                print $0 >> outfile2;   
            }
        }
    ' "$2"
}

lines_matching () {
    grep -n -f <(echo "$1") <(echo "$2") | cut -d ':' -f 1
}

file_a_cols=$(awk '{printf "%s %s %s %s\n", $2, $9, $3, $4; }' "$file_a")
file_b_cols=$(tr -s ' ' < "$file_b")

matched_lines_file_a=$(lines_matching "$file_b_cols" "$file_a_cols")
matched_lines_file_b=$(lines_matching "$file_a_cols" "$file_b_cols")

print_to_files "$matched_lines_file_a" "$file_a" "$file_c" "new_$file_a"

print_to_files "$matched_lines_file_b" "$file_b" "/dev/null" "$file_d"

答案3

perl -MFatal='open,close' -ali -ne '
   BEGIN{
      open FILEC, ">", "FileC.out";
      open FILED, ">", "FileD.out";
   }

   if ( @ARGV ) { # FileB readin
      if ( $. == 1 ) {
         push @names, @F;
         print FILED $_;
      } else {
         push @A, join $/, @F;
         push @B, $_;
      }
      print;
   } else { # FileA readin
      if ( $. == 1 ) {
         print FILEC $_;
         print;
         @remap =
            map {
               my $n = $names[$_];
               grep { $n eq $F[$_] } 0 .. $#F;
            } 0..$#names;
      } else {
         my $n = join $/, @F[@remap];
         if ( my($id) = grep { $n eq $A[$_] } 0 .. $#A ) {
            push @IDs, $id;
            print FILEC $_;
         } else {
            print;
         }
      }
   }

   eof and $. = 0;

   END{
      splice(@B, $_, 1) for @IDs;
      @B and print FILED $_ for @B;
      close $_ for *FILEC, *FILED;
   }
' FileB FileA

此后,将创建文件“FileC.out”、FileD.out。 FileA 已修改,FileB 保持不变。

该流程与您之前的查询中一样,只是添加了归档处理。

相关内容