さて、私が何をすべきかを説明しようとします。デフォルトでは、次の例に示すように2つのCSVファイルがあります。
ファイル1:
Column 1, Column 2
abc , 123
def , 234
adf , 567
ファイル2
Column 1, Column 2
abc , 123
def , 234
adf , 578
次の手順を実行するには、シェルスクリプトまたは単純なコマンドを作成する必要があります。
- 列1に基づいて2つのファイルを並べ替える
- 以下を 1 行ずつ実行します。
- ファイル1の列1を使用して、ファイル2の列1から値を取得します。
- 見つかった場合は、ファイル1の列2の値をファイル2の列2の値と比較します。
- 一致する場合は、列1、2、および3に「確認済み」と書いてファイルを分割します。
- 一致するものがない場合は、列1、列2、および「失敗」をファイルごとに作成します。
- ファイル1の列1を使用して、ファイル2の列1から値を取得します。
これにより、2 つの出力ファイルが生成されます。最初のファイルには一致する列 1 と 2 で見つかったすべての項目が含まれ、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番目のファイルを噛み始めると、テスト用の配列を事前に埋めることができます。
答え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
- 2つの
%
署名ハッシュは、%csv1
各%csv2
ファイルから取得したキー/値の格納場所を表します。 - 空白の切り捨て、ヘッダー操作、および完全性チェックは、実行中のコードに詳細を追加します。
- 「exists」などのファイル演算子は、
.e
既存の出力ファイルを上書きしないようにします。ファイルハンドルは、:a
を表すオプションで開きます:append
。 - 出力ループでの
%csv1
キーを見つけて%csv2
確認してください。対応する文字列(eq
同じ)value
s。 「確認済み」、「不一致」、または「存在しない」の3つの文字列のいずれかを返します。 - 出力は開いている出力ファイルハンドルに1行ずつ追加され、スクリプトの最後で閉じられます。
注:確認したい場合数値的等価物各キーの値は次のとおりです。
%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