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는 변경되지 않은 상태로 유지됩니다.
프로세스는 보관 처리가 추가된 이전 쿼리와 동일합니다.