Bodo has already pointed out the issues with your code and corrected them. I'm giving alternative answers.
Using awk
only. This is essentially the same as in Bodo's answer, but it does not split the data from the first file into individual arrays. It also does not use a magic numerical constant (-1 in their code) to initialise the smallest distance seen but instead uses the fact that an unset value in awk
is empty when interpreted as a string.
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
Other ways:
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 }'
The above first use join
on non-existing fields to create a relational cross-product of all the input data (it combines each line of one file with all the lines of the other file).
That data will look like this:
123 pattern1 12 a
123 pattern1 34 b
[etc.]
601 pattern3 566 i
601 pattern3 993 o
It then calculates a distance metric and inserts this as a new first column:
12321 123 pattern1 12 a
7921 123 pattern1 34 b
[etc.]
1225 601 pattern3 566 i
153664 601 pattern3 993 o
The two calls to sort
first order this data numerically on the distance metric, then it uses the data from the first file as the sorting key and does a stable unique sort. This will discard all but the first instance of the data from the first file, leaving, in this case, three lines:
9 123 pattern1 120 f
2704 452 pattern2 400 oo
1225 601 pattern3 566 i
From this, we pick out the columns we're interested in using awk
:
123 pattern1 f
452 pattern2 oo
601 pattern3 i
1 x
and3 y
exist in file2 and2 z
exists in file1 should the output be2 z x
or2 z y
or2 z x y
or something else?very unlikely to happen
=will happen unexpectedly when I least want it
.