usando divisão no script awk

0

Eu tenho um arquivo descrevendo frequências alélicas e estou tentando usar o awk para imprimir linhas se qualquer uma das freqüências nas duas últimas colunas for igual ou maior que 0,01. Abaixo está o formato do arquivo de frequência: Estou interessado nas duas últimas freqüências.

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

De meu conhecimento limitado do awk, escrevi o seguinte código.

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

No entanto, o arquivo de saída myfilteredfile.txt está vazio. Eu esperava que o arquivo de saída teria impresso:

2L      10000133
2L      10000374

... porque ambas as linhas contêm uma frequência nas duas últimas colunas que é igual ou maior que 0,01. Algum conselho?

    
por Chris Allan 15.09.2017 / 07:55

3 respostas

1
$  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

Isso divide os dois últimos campos individualmente no caractere / e armazena as partes nas duas matrizes a e b . Se uma das divisões, quando executada, resultar em um número maior que 0,01, os dois primeiros campos serão exibidos.

$NF é o valor do último campo (coluna) no registro de entrada (linha). e $(NF-1) é o segundo ao último valor do campo.

O problema com o seu código é que você está fazendo tudo em um bloco BEGIN . Este bloco é principalmente para inicialização e será executado antes de todos os dados terem sido realmente lidos. Há também um problema com o valor escolhido de FS que as outras respostas apontam.

Você também não precisa citar números quando eles são usados como números.

    
por 15.09.2017 / 08:21
4

Existem dois problemas com o seu script existente.

O primeiro é o separador: você quer dividir em execuções de espaços e barra; Portanto, você precisa especificar uma expressão regular que corresponda a isso e usar isso como FS : FS="[ /]+" .

A segunda é que todo o seu código está no bloco BEGIN . Você precisa inicializar os separadores no bloco BEGIN (ou em outro lugar, por exemplo, usando parâmetros AWK específicos) e usar um bloco de correspondência para processar as linhas.

Esta versão funciona:

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

A rigor, seria melhor usar 0.01 em vez de "0.01" , já que você está combinando valores numéricos:

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

Em awk BEGIN{...} partes está em execução antes de ler a entrada da linha de entrada, portanto, em seu código, na verdade awk não está lendo nenhuma entrada, é por isso que não está retornando nada. Se você quiser alimentá-lo, você precisa usar getline , mas ele lerá apenas uma linha, você pode usar for loop para ler tudo.

outro problema é quando você usa FS="/" para dividir as linhas nos campos delimitados por / , mas o problema é $8 não sai, pois os campos máximos são apenas 5 e os arquivados são assim 125 115 , 131 0 , 125 16 , etc.

Você pode usar este código para obter o que deseja. Observe também que awk pode ler diretamente do arquivo não necessário usando cat there

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

Tags