awk 스크립트에서 나누기 사용

awk 스크립트에서 나누기 사용

대립유전자 빈도를 설명하는 파일이 있고 마지막 두 열의 빈도 중 하나가 0.01 이상인 경우 awk를 사용하여 행을 인쇄하려고 합니다. 주파수 파일의 형식은 다음과 같습니다. 저는 마지막 두 주파수에 관심이 있습니다.

2L      10000133        A      125/125 115/131 0/125   16/131
2L      10000374        A      121/124 143/143 3/124   0/143

awk에 대한 제한된 지식을 바탕으로 다음 코드를 작성했습니다.

cat myfile.txt |
awk ' BEGIN { {FS="/"}{OFS="\t"}
     if( ($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01"))
             { print $1,$2 }
            }' > myfilteredfile.txt

그러나 출력 파일 myfilteredfile.txt는 비어 있습니다. 출력 파일이 인쇄될 것으로 예상했습니다.

2L      10000133
2L      10000374

...두 행의 마지막 두 열의 빈도가 0.01보다 크거나 같기 때문입니다. 어떤 제안이 있으십니까?

답변1

기존 스크립트에는 두 가지 문제가 있습니다.

첫 번째는 구분 기호입니다. 공백과 슬래시로 분할하려면 해당 정규식을 지정하고 다음과 같이 사용해야 합니다 FS.FS="[ /]+"

두 번째는 모든 코드가 BEGIN블록 안에 있다는 것입니다. BEGIN초기화 블록(또는 다른 곳)에 구분 기호가 필요합니다 .예를 들어특정 AWK 매개변수 사용) 그런 다음 matcher 블록을 사용하여 해당 라인을 처리합니다.

이 버전의 작동 방식:

awk 'BEGIN { FS="[ /]+"; OFS="\t" }
     (($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01")) {
         print $1, $2
     }' myfile.txt

엄밀히 말하면 숫자 값을 일치시키려고 하므로 0.01대신 사용하는 것이 더 좋습니다 ."0.01"

awk 'BEGIN { FS="[ /]+"; OFS="\t" }
     (($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01)) {
         print $1, $2
     }' myfile.txt

답변2

$  awk '{ split($(NF-1),a,/\//) } { split($NF,b,/\//) } a[1]/a[2] > 0.01 || b[1]/b[2] > 0.01 { print $1, $2 }' file.in
2L 10000133
2L 10000374

이렇게 하면 마지막 두 필드를 문자별로 개별적으로 분할 /하고 해당 부분을 두 개의 배열 a과 에 저장합니다 b. 나누기 결과가 0.01보다 큰 숫자가 되면 처음 두 필드가 출력됩니다.

$NF입력 레코드(행)의 마지막 필드(열) 값입니다. $(NF-1)두 번째 필드의 값 입니다 .


코드의 문제는 BEGINdo everything 블록 내에서 모든 작업을 수행한다는 것입니다. 이 블록은 주로 초기화에 사용되며 실행됩니다.앞으로실제로 읽은 데이터가 없습니다. FS다른 답변에서 지적한 선택 값에도 문제가 있습니다.

또한 숫자로 사용될 때 숫자를 인용할 필요가 없습니다.

답변3

In 부분 awkBEGIN{...}입력에서 입력 줄을 읽기 전에 실행되므로 awk코드에서 실제로 입력을 읽지 않으므로 아무 것도 반환하지 않습니다. 먹이를 주고 싶다면 를 사용해야 getline하지만 한 줄만 읽게 되므로 for루프를 사용하여 모두 읽을 수 있습니다.

또 다른 문제는 이를 사용하여 FS="/"행을 로 구분된 필드로 분할 하는 경우이지만 최대 필드가 5개에 불과하고 제출된 필드가 다음과 같기 때문에 /문제가 없습니다 .$8125 115131 0125 16

이 코드를 사용하여 원하는 것을 얻을 수 있습니다. 또한 awk파일에서 직접 읽을 수 있으므로 cat거기에서 사용할 필요가 없습니다.

awk -F'[/ ]+' 'BEGIN{ OFS="\t"}
    {if( ($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01))
    { print $1,$2 }
}'  infile

관련 정보