2つのファイルがあります。
ファイル1:
123 pattern1
452 pattern2
601 pattern3
ファイル2:
12 a
34 b
88 ee
120 f
333 qw
400 oo
566 i
993 o
私が望むのは、file2の最初の列でfile1の最初の列の各行に最も近い値を見つけて、file2の対応する2番目の列をfile1(新しいファイル内)に追加することです。
両方のファイルに重複した値はありません。
希望の出力:
123 pattern1 f
452 pattern2 oo
601 pattern3 i
awkを使ってみましたが、うまくいきません。
awk 'NR==FNR { seq[$2]=$1; next }
{
d = $1 - seq[$2];
d = d < 0 ? -d : d;
v = $1;
next
}
{
m = $1 - seq[$2];
m = m < 0 ? -m : m
}
m < d {
d = m;
v = $1
}
{ print $0 }' file1.txt file2.txt
答え1
博多には指摘コードに問題があり、修正してください。私は代替答えを提供しています。
のみ使用してくださいawk
。これは本質的に最初のファイルのデータを別の配列に分割しないことを除いて、Bodoの答えと同じです。また、表示された最小距離を初期化するために、魔法の数値定数(コード内の-1)を使用せずに、代わりにawk
文字列として解釈されたときに設定されていない値が空であるという事実を使用します。
awk '
NR == FNR { num[$0] = $1; next }
{
for (a in num) {
d = (num[a]-$1)^2
if (min[a] == "" || d < min[a]) {
min[a] = d; symb[a] = $2
}
}
}
END { for (a in symb) print a, symb[a] }' file1 file2
他の方法:
join -1 3 -2 3 file1 file2 |
awk '{ print ($1-$3)^2, $0 }' |
sort -k 1,1n | sort -su -k 2,3 |
awk '{ print $2, $3, $5 }'
上記は、最初にjoin
存在しないフィールドを使用して、すべての入力データのリレーショナル交差積を生成します(あるファイルの各行を他のファイルのすべての行と結合します)。
データは次のとおりです。
123 pattern1 12 a
123 pattern1 34 b
[etc.]
601 pattern3 566 i
601 pattern3 993 o
次に距離測定を計算し、それを新しい最初の列に挿入します。
12321 123 pattern1 12 a
7921 123 pattern1 34 b
[etc.]
1225 601 pattern3 566 i
153664 601 pattern3 993 o
これら2つの呼び出しは、sort
最初に距離測定に基づいてこのデータを数値的にソートし、次に最初のファイルのデータをソートキーとして使用して、安定した一意のソートを実行します。これにより、最初のファイルの最初のデータインスタンスを除くすべてのエントリが削除され、この場合は3行が残ります。
9 123 pattern1 120 f
2704 452 pattern2 400 oo
1225 601 pattern3 566 i
ここで興味のある列を選択してくださいawk
。
123 pattern1 f
452 pattern2 oo
601 pattern3 i
答え2
スクリプトにはいくつかの問題がありますawk
。 2番目のワークブロックには条件がなく、で終わりますnext
。これが他のブロックが決して実行されない理由です。
2番目のファイルのフィールド2をインデックスとして使用することは、seq
フィールド2の値がfile1とfile2で異なるため意味がありません。
awk 'NR==FNR {
seq[NR] = $1;
name[NR] = $2;
delta[NR] = -1;
count = NR;
next
}
{
for(i = 1; i <= count; i++) {
d = $1 - seq[i];
d = d < 0 ? -d : d;
if((delta[i] < 0) || (d < delta[i])) {
delta[i] = d;
val[i] = $2;
}
}
}
END {
for(i = 1; i <= count; i++) {
printf "%s %s\t%s\n", seq[i], name[i], val[i]
}
}' file1.txt file2.txt
印刷
123 pattern1 f
452 pattern2 oo
601 pattern3 i
答え3
ファイルの順序を変更すると、もう少しコンパクトになります。
awk '
NR==FNR {A[$1]=$2; next}
{arg=1000
for(i in A){
cmp = sqrt(($1-i)^2)
if(cmp < arg)
{arg=cmp; third=A[i]}
}
print $0, third}
' file2 file1
sqrt(X^2)
絶対値の機能を実行する式の一部