좋아, 내가 무엇을 해야 하는지 설명하려고 노력할게. 기본적으로 아래 예와 같이 두 개의 CSV 파일이 있습니다.
파일 1:
Column 1, Column 2
abc , 123
def , 234
adf , 567
파일 2
Column 1, Column 2
abc , 123
def , 234
adf , 578
다음을 수행하려면 쉘 스크립트나 간단한 명령을 작성해야 합니다.
- 열 1을 기준으로 두 파일 정렬
- 다음을 한 줄씩 수행하십시오.
- 파일 1의 열 1을 사용하여 파일 2의 열 1에서 값을 검색합니다.
- 찾은 경우 파일 1의 열 2에 있는 값을 파일 2의 열 2에 있는 값과 비교합니다.
- 일치하는 경우 1, 2, 3열에 "확인됨"이라고 써서 파일을 분리하세요.
- 일치하는 항목이 없으면 열 1, 열 2 및 "실패"를 파일별로 작성합니다.
- 파일 1의 열 1을 사용하여 파일 2의 열 1에서 값을 검색합니다.
그러면 두 개의 출력 파일이 생성됩니다. 첫 번째 파일에는 일치하는 열 1과 2에서 발견된 모든 항목이 포함되고, 두 번째 파일에는 실패한 열 1 조회 또는 발견된 열 1이 포함되지만 열 2 위치에는 일치 항목이 없으므로 기본적으로 열 1을 키로 사용합니다. 2열을 확인하세요.
답변1
다음 입력 파일이 주어지면:
$ cat in1 in2
Column 1, Column 2
abc , 123
def , 234
adf , 567
Column 1, Column 2
abc , 123
def , 234
adf , 578
먼저 이를 정렬한 다음 단일 파일로 연결할 수 있습니다.
$ sort in1 > in1.sorted; sort in2 > in2.sorted; paste in{1,2}.sorted
Column 1, Column 2 Column 1, Column 2
abc , 123 abc , 123
adf , 567 adf , 578
def , 234 def , 234
awk
여기서는 쉼표가 도움이 되지만, 먼저 쉼표를 제거해야 합니다 sed
.
$ paste in{1,2}.sorted | sed s/,//g
Column 1 Column 2 Column 1 Column 2
abc 123 abc 123
adf 567 adf 578
def 234 def 234
그런 다음 다음을 통해 빠르게 덤프할 수 있습니다 awk
.
$ paste in{1,2}.sorted | sed s/,//g | awk '$2 == $4 {print $1,"Validated"}; $2 != $4 { print $1,"Failed"}'
Column Failed
abc Validated
adf Failed
def Validated
이 작업은 raw 를 사용하여 수행할 수도 있습니다 awk
. 헤더 행을 제거할 수 있고 동일한 순서의 동일한 데이터에 의존하지 않으므로 정렬이 필요하지 않다는 장점이 있습니다.
$ awk 'FNR != 1 && NR == FNR {data[$1]=$3} FNR != 1 && NR != FNR {if(data[$1]==$3) {print $1, "Validated"} else {print $1, "Failed"} }' in{1,2}
abc Validated
adf Failed
def Validated
이는 몇 가지 마법의 awk
내장 변수와 이와 관련된 트릭에 의존합니다.
NR
-처리된 총 레코드 수FNR
- 총 레코드 수현재 파일에다루다FNR != 1
- 각 파일의 첫 번째 줄을 건너뜁니다. (헤더는 데이터로 처리되지 않습니다.)NR != FNR
- 첫 번째 파일을 완전히 읽고 후속 파일을 읽기 시작한 후에만 실행됩니다. 이를 통해data
두 번째 파일을 씹기 시작하면 테스트용 배열을 미리 채울 수 있습니다.
답변2
다른 사람이 이 글을 읽고 필요할 경우를 대비해 다음과 같이 문제를 해결했다고 생각합니다. 다시 한 번 감사드립니다.
FNR == NR {
for (i = 2; i <= NF; i++) { a[i,$1] = $i }
b[$1];
next;
}
($1 in b) { # check if row in file2 existed in file1
for (i = 2; i <= NF; i++) {
if (a[i,$1] == $i)
printf("%s->col%d: %s vs %s: Valid\n", $1, i-1, a[i,$1], $i);
else
printf("%s->col%d: %s vs %s: Failure\n", $1, i-1, a[i,$1], $i);
}
delete b[$1]; # delete entries which are processed
}
END {
for (left in b) { # look which didn't match
for (i = 2; i <= NF; i++)
printf("%s->col%d: %s vs (blank): Not Equal\n", left, i-1, a[i,left])
}
}
답변3
사용행복하다(이전 Perl_6)
#! /usr/bin/env raku
#INPUT AND HEADERS:
my $csv1 = "Veyron1.txt".IO;
my $csv2 = "Veyron2.txt".IO;
my $hdr1 = "Key,Value,Verified";
my $hdr2 = "Key,Value,Failed";
#HASH STORAGE (Below, beware of `skip`ping header in headerless file!):
my %csv1; for $csv1.lines.skip.map( *.split(",").map( *.trim)) {
%csv1.push: .[0] => .[1]
};
my %csv2; for $csv2.lines.skip.map( *.split(",").map( *.trim)) {
%csv2.push: .[0] => .[1]
};
#SANITY CHECKS:
die "multiple values per key in file_1" if any(%csv1.values.map: *.elems > 1).so;
die "multiple values per key in file_2" if any(%csv2.values.map: *.elems > 1).so;
#OUTPUT FILE PREP W/ HEADER:
!("Veyron_output_verified.txt".IO.e) && (my $fh1 = "Veyron_output_verified.txt".IO.open: :a);
!("Veyron_output_failed.txt".IO.e) && (my $fh2 = "Veyron_output_failed.txt".IO.open: :a);
$fh1.put: $hdr1;
$fh2.put: $hdr2;
#OUTPUT LOOP:
for %csv1.keys.sort -> $id {
if %csv2{$id}:exists {
if %csv1{$id} eq %csv2{$id} {
$fh1.put: ($id, %csv1{$id}, "verified").join: ",";
}
else {
$fh2.put: ($id, %csv1{$id}, "mismatch").join: ",";
}
}
else {
$fh2.put: ($id, %csv1{$id}, "absent").join: ",";
}
}
$fh1.close;
$fh2.close;
이것은 Perl 프로그래밍 언어 계열인 Raku로 작성된 스크립트입니다. Perl과 마찬가지로 Raku에는 키/값 데이터 구조와 다양한 파일 연산자가 있어 이러한 성격의 문제를 해결하는 데 이상적입니다. 간단히:
- 상단의
$
-sigiled는 파일 핸들(실제로 는 객체)을$csv1
의미합니다 . Raku에서는 기호가 동일하게 유지되기 때문에 ...$csv2
.IO
- 두 개의
%
서명 해시는%csv1
각각%csv2
각 파일에서 얻은 키/값의 저장 위치를 나타냅니다. - 공백 자르기, 헤더 조작 및 온전성 검사는 실행 중인 코드에 세부 정보를 추가합니다.
- "exists"와 같은 파일 연산자는
.e
기존 출력 파일을 덮어쓰지 않도록 합니다. 파일 핸들은:a
를 나타내는 옵션과 함께 열립니다:append
. - 출력 루프에서
%csv1
의 키를 찾아%csv2
확인하세요 .상응하는 문자열(eq
동일)value
s. "확인됨", "일치하지 않음" 또는 "존재하지 않음"의 세 가지 문자열 중 하나를 반환합니다. - 출력은 열려 있는 출력 파일 핸들에 한 줄씩 추가되며 스크립트 끝에서 닫힙니다.
참고: 확인하고 싶다면수치적 등가물각 키의 값은 다음과 같습니다.
%csv1{$id} eq %csv2{$id}
그리고: %csv1{$id} == %csv2{$id}
출력 예("확인됨"):
Key,Value,Verified
abc,123,verified
def,234,verified
출력 예("실패"):
Key,Value,Failed
adf,567,mismatch
Leku 참고 자료:
https://docs.raku.org
https://raku.org
관련 Perl 스크립트:
https://www.perlmonks.org/?node_id=805106