두 파일에서 숫자 범위를 추출하려고 합니다.
$cat 파일1.txt
chr1 69509
chr1 69511
chr1 71000
chr1 358112
chr1 586874
chr1 744200
. . .
$cat 파일2.txt
chr1 69091 70005
chr1 358070 358183
chr1 586842 586955
chr1 744195 744343
. . .
원하는 출력:
69509 CHR1 69091 70005
69511 CHR1 69091 70005
71000범위 초과
358112 CHR1 358070 358183
586874 CHR1 586842 586955
744200
아래는 내 awk 코드입니다.
awk 'NR==FNR{x[$1] = $2; next;}{for (i in x) {if (x[i] > $2 && x[i] < $3)print x[i], $1,$2,$3;else{print x[i], "out of range"}}}' file1.txt file2.txt
그러나 이 코드에서 반환된 출력에는 마지막 NR에 대한 데이터만 포함됩니다.
예를 들어,
744200 범위를 벗어났습니다 . 744200
범위를 벗어났습니다
. 744200 범위를 벗어났습니다.
744200 chr1 744195 744343
NR 및 FNR과 관련이 있는 것 같은데 어떻게 해야 할지 모르겠습니다.
답변1
x
이는 첫 번째 파일의 모든 줄에 $1
대해 동일한 배열을 입력하기 때문입니다. chr1
따라서 각 행에서 배열 내용은 동일한 키를 기반으로 인덱싱되고 $2
. 따라서 파일 끝에 도달할 때쯤에는 배열에 항목이 있게 됩니다.x['chr1']=744200
행을 고유하게 저장해야 합니다. 키를 튜플로 저장 $1 FS $2
하고 논리를 다음과 같이 수정합니다.
awk 'NR == FNR { x[$1 FS $2] = $2; next }{
for (key in x) {
split(key, arr)
if (arr[2] > $2 && arr[2] < $3)
print arr[2], $0
else {
print arr[2], "out of range"
}
}
}' file1 file2
두 파일의 첫 번째 열이 동일한 행에서만 범위 검사를 수행하도록 논리를 개선하려면 if
다음과 같은 조건을 추가하세요.
if ( (arr[2] > $2 && arr[2] < $3) && ( $1 == arr[1] ) )
답변2
귀하의 예에서와 같이 file2 범위가 겹치지 않는다고 가정합니다.
$ cat tst.awk
NF==3 { beg=$2; end=$3; all=$0; next }
{ print $2, ( ($2 >= beg) && ($2 <= end) ? all : "out of range" ) }
$ sort -sk2n file2 file1 | awk -f tst.awk
69509 chr1 69091 70005
69511 chr1 69091 70005
71000 out of range
358112 chr1 358070 358183
586874 chr1 586842 586955
744200 chr1 744195 744343
GNU 정렬("안정적인 정렬")을 사용하여 동일한 s가 지정된 -s
이 항목 앞에 file2 항목이 인쇄되도록 합니다.file1
$2