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의 해당 두 번째 열을 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
이 두 호출은 sort
먼저 거리 측정법을 기준으로 이 데이터를 수치적으로 정렬한 다음 첫 번째 파일의 데이터를 정렬 키로 사용하여 안정적이고 고유한 정렬을 수행합니다. 이렇게 하면 첫 번째 파일의 첫 번째 데이터 인스턴스를 제외한 모든 항목이 삭제되고 이 경우 세 줄이 남습니다.
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
. 두 번째 작업 블록에는 조건이 없으며 로 끝납니다 next
. 이것이 다른 블록이 결코 실행되지 않는 이유입니다.
두 번째 파일의 필드 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)
절대값의 기능을 수행하는 표현식의 일부