파일 B의 행이 파일 A의 여러 열과 일치하는 경우 파일 A의 행을 삭제하고 일치하는 행을 파일 C에 배치하고 일치하지 않는 행을 파일 D에 배치합니다.

파일 B의 행이 파일 A의 여러 열과 일치하는 경우 파일 A의 행을 삭제하고 일치하는 행을 파일 C에 배치하고 일치하지 않는 행을 파일 D에 배치합니다.

2개의 파일이 있습니다 -파일 A이것은 10개 이상의 열과 약 15,000개의 행으로 구성된 기본 파일이며,문서 B4개의 열과 약 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 명령을 실행합니다(참고 - 시스템 기능에는 코드 삽입 위험이 있으므로 그에 따라 위험을 평가하십시오). 일치하는 항목이 없으면 해당 행을 문서에 출력합니다. 디.

행동:

awk -f awkscriptfile fileB fileA

답변2

용법: ./processing.sh

이 스크립트는 원본 파일을 변경하지 않고 file_A생성합니다 new_file_A. 원본을 삭제 file_A하고 이름을 변경 new_file_A하는 코드 몇 줄을 추가할 수 있습니다 file_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는 변경되지 않은 상태로 유지됩니다.

프로세스는 보관 처리가 추가된 이전 쿼리와 동일합니다.

관련 정보