A, B 두 개의 파일이 있습니다. 파일 A에는 4개의 열과 600,000개의 행이 있습니다. 파일 B에는 4개의 열과 5000개의 행이 있습니다. 예:
파일-A:
ENSB1 1 12245 0.53 0.002
ENSB2 1 13400 0.27 0.0003
ENSB3 1 14780 0.13 0.00001
ENSB4 1 15201 0.33 0.9
ENSB5 2 56259 0.70 0.0002
ENSB6 2 57000 0.42 0.00004
ENSB7 2 58200 0.50 0.5
파일-B:
1 12000 15000 G1
1 14000 16000 G2
2 56000 59000 G3
File-B의 첫 번째 줄을 선택하고 싶습니다. 그런 다음 파일 A의 열 3에 있는 값이 파일 B의 열 2와 3에 있는 값의 범위 내에 속하도록 파일 A의 여러 행을 식별하려고 합니다. 파일 A의 2열도 파일 B의 2열과 3열의 값 범위에 속하며, 파일 B의 1열의 값은 일치합니다. File-A의 여러 행이 위 조건을 충족할 것으로 예상합니다. 위 기준에 따라 여러 행이 식별되면 파일 A의 해당 행 중 5열의 가장 낮은 값이 선택되어 파일 B의 해당 행에 있는 새 열에 기록됩니다. File-B의 모든 줄에 대해 이 단계를 반복합니다.
예상되는 새 파일:
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
저는 Linux 명령을 처음 배우는 사람인데 누구든지 도움을 주시면 좋을 것 같습니다.
답변1
노력하다
awk 'NR==FNR {Line[FNR] = $0 # first file processing
Cat[FNR] = $1
Min[FNR] = $2
Max[FNR] = $3
Low[FNR] = 1E10 # initialize to high number so first value from file2 will be lower
ML = FNR
next
}
# second file processing; if same Category and $3 between Min and Max, and $5 lower than before one, keep $5
{for (i=1; i<=ML; i++) if ($2 == Cat[i] &&
$3 >= Min[i] &&
$3 <= Max[i] &&
$5 < Low[i]) Low[i] = $5
}
END {for (i=1; i<=ML; i++) print Line[i], Low[i]
}
' File-B File-A
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
많은 설명이 필요하지 않습니다. 첫 번째 파일( NR == FNR
)부터 시작하여 범주 및 범위/경계 값을 유지하고 첫 번째 읽기의 실제 값이 더 낮도록 Low 배열 요소를 설정합니다. 두 번째 파일을 처리할 때 위에 기록된 데이터 세트를 반복합니다. 새로 읽은 레코드가 항목과 동일한 카테고리를 갖고 $3이 Min과 Max 사이에 있고 $5가 이전에 얻은 레코드보다 낮은 경우 $5를 배열에 유지합니다 Low
. 이 END
섹션에서는 기록된 행과 얻은 Low
값을 표준 출력으로 인쇄합니다.
답변2
any awk
및 any를 사용하십시오 sort
.
$ cat tst.sh
#!/usr/bin/env bash
sort -k5,5n -- "$1" |
awk '
NR==FNR {
if ( !($3 in map) ) {
keys[++numKeys] = $3
map[$3] = $5
}
next
}
{
for ( k=1; k<=numKeys; k++ ) {
key = keys[k]
if ( ($2 <= key) && (key <= $3) ) {
print $0, map[key]
next
}
}
}
' - "$2"
$ ./tst.sh 'File-A' 'File-B'
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
중복된 $3 값이 있는 경우 위의 내용은 연관된 가장 낮은 $5 를 올바르게 사용합니다 File-A
.