Bash: 숫자 범위를 일치시켜 행 필터링

Bash: 숫자 범위를 일치시켜 행 필터링

파일이 있어요시험필드 포함:카토, 그리고위치.

1   7100
1   35000
1   49321
1   49759
2   44842
2   52794
2   53558
3   53859
3   54013
3   55172

파일이 있어요필드 포함:카토,시작그리고멈추다.

1   6408    8000
1   11822   16373
1   18716   23389
1   27690   34330
1   36552   39191
1   39313   44565
2   44839   50247
2   60987   65017
2   65705   71523

내 목표는 파일에서 줄을 선택하는 것입니다pos파일의 where 필드시험범위 내에 속하다시작그리고멈추다기록한 것. 지정된 시간 내에 게임을 플레이해야 한다는 제한이 있습니다.카토그룹. 두 파일 모두 필드 1과 2를 기준으로 정렬됩니다. 그건 그렇고, 내 두 개의 실제 파일에는 다른 많은 필드가 있습니다.

이 예제 데이터 세트의 예상 결과는 다음과 같습니다.

1   6408    8000
2   44839   50247

제가 섞어 놓은 스크립트가 있습니다.

k=1;
data_test=$(cat "test")
data_db=$(cat "db")
while read -r line
do
  # helps to keep count of test rows
  printf "$k \n"

  # get cato
  cato=$(echo $line | awk '{print $1}')
  # get pos
  pos=$(echo $line | awk '{print $2}')
  # get number of chars in pos (to reduce number of lines awk needs to look through later)
  pos_chr=$(echo -n $pos | wc -c)
  # get lines in db that start with cato and pos chars match start or stop
  matched=$(echo "$data_db" | grep -Ew "^$cato" | grep -Ew "[0-9]{$pos_chr}")
  #echo "$db_cat"

  # if matched is not empty
  if [ ! -z "$matched" ]; then
    # use awk to print lines in db where pos > start and pos < stop
    echo "$matched" | awk -v apos='$pos' 'BEGIN{OFS="\t"}{if(apos >= $2 && apos <= $3) print $0}'
    #check
    #echo "$matched" | awk -v apos=$pos 'BEGIN{OFS="\t"}{print apos,$0}'
  fi

  ((k=k+1))
done <<< "$data_test"

awk마지막 단계에서 비교가 이루어지지 않은 것 같습니다 . 모든 것이 마지막 단계까지 진행되는 것 같은데, 무슨 일이 일어나고 있는지 잘 모르겠습니다. 누군가 오류를 봤을 수도 있습니다. 더 좋은 방법이 있나요?

답변1

단일 GNU 사용awk프로그램( Gawkv4.0부터):

awk 'NR==FNR{ a[$1][$2]; next }
     $1 in a{ 
         for (i in a[$1]) 
             if (i >= $2 && i <= $3) { print $0; break }
     }' test db

산출:

1   6408    8000
2   44839   50247

답변2

join간단하게 사용하세요 test:

$ cat is-between.sh
#!/bin/bash

while read cato start stop pos; do
    [ $start -le $pos -a $pos -le $stop ] && echo "$cato $start $stop"
done < <(join db test)

$ ./is-between.sh
1 6408 8000
2 44839 50247

관계형 데이터가 있습니다. 한 파일의 키-값은 다른 파일의 키-값과 한 줄씩 일치합니다. join이것들을 하나로 모으는 도구입니다. 이를 실행하면 데이터베이스에 있는 데이터와 동일한 결과를 볼 수 있습니다 join db test.SELECT * FROM db JOIN test on test.cato=db.cato

이로써 시작, 끝, 위치를 한 줄에 넣는 줄이 생겼습니다. 범위를 확인하기 위해 a를 사용하여 이를 반복하는 test것은 쉽습니다.

관련 정보