Como contar a ocorrência de um padrão em uma linha

8

Eu tenho um arquivo que tem três colunas. A coluna 3 contém nomes de genes e é assim:

Rv0729,Rv0993,Rv1408  
Rv0162c,Rv0761c,Rv1862,Rv3086  
Rv2790c

Como posso imprimir o número de genes em cada linha?

    
por Saisha 08.03.2017 / 10:49

4 respostas

10

Você simplesmente deseja adicionar uma coluna com a contagem de colunas. Isso pode ser feito usando awk :

$ awk -F ',' '{ printf("%d,%s\n", NF, $0) }' data.in
3,Rv0729,Rv0993,Rv1408
4,Rv0162c,Rv0761c,Rv1862,Rv3086
1,Rv2790c

NF é uma variável awk que contém o número de campos (colunas) no registro atual (linha). Imprimimos esse número seguido por uma vírgula e o restante da linha, para cada linha.

Uma alternativa (mesmo resultado, mas pode parecer um pouco mais limpa):

$ awk -F ',' 'BEGIN { OFS=FS } { print NF, $0 }' data.in

FS é o separador de campos que awk usa para dividir cada registro em campos, e definimos isso para uma vírgula com -F ',' na linha de comando (como na primeira solução). OFS é o separador de campo output e definimos que seja o mesmo que FS antes de ler a primeira linha de entrada.

    
por 08.03.2017 / 11:08
5

Se você quisesse contar o número de ocorrências do padrão Rv[0-9]{4}c? em oposição ao número de campos delimitados por vírgulas, como sugere o assunto da sua pergunta, você poderia:

 awk '{print gsub(/Rv[0-9]{4}c?/, "&"), $0}'
    
por 08.03.2017 / 11:22
4

Uma abordagem Perl:

$ perl -F, -pae 's/^/$#F+1 . ","/e' file
3,Rv0729,Rv0993,Rv1408  
4,Rv0162c,Rv0761c,Rv1862,Rv3086  
1,Rv2790c

O -a faz com que perl se comporte como awk e divida cada linha de entrada na string dada por -F e salve os campos resultantes na matriz @F . Portanto, $#F será o maior índice de array em @F e, como as matrizes começam a contar em 0 , $#F+1 será o número total de elementos na matriz. O -p significa "imprimir todas as linhas de entrada após aplicar o script dado por -e . O s/// é o operador de substituição e aqui estavam substituindo o início da linha ( ^ ) pelo número de campos + 1 e uma vírgula ( $#F+1 . "," ).

    
por 08.03.2017 / 11:12
1

Sua pergunta afirma que a coluna 3 contém nomes de genes. Presumo que sua entrada real seja a seguinte:

column1 column2 Rv0729,Rv0993,Rv1408  
column1 column2 Rv0162c,Rv0761c,Rv1862,Rv3086  
column1 column2 Rv2790c

Cada nome de gene na coluna3 contém a substring Rv principal. Assim, podemos contá-los em python da seguinte forma:

$ python -c  "import sys;print map(lambda x: x.split()[2].count('Rv'),sys.stdin.readlines())"  < input.txt               
[3, 4, 1]

A lista resultante mostra a contagem de genes em cada linha, em sua respectiva ordem. Se quisermos torná-lo mais detalhado e incluir a possibilidade de que os genes não contenham a string "Rv" (mas mantenha a suposição de que column3 é uma string de valor separada por vírgulas), também podemos fazer o seguinte:

#!/usr/bin/env python
import sys
with open(sys.argv[1]) as fd:
    for index,line in enumerate(fd):
        columns = line.strip().split()
        num_genes=len(columns[2].split(","))
        print("Line "+str(index)+" contains "+str(num_genes))

Execução de teste:

$ ./count_genes.py input.txt                                                                                             
Line 0 contains 3
Line 1 contains 4
Line 2 contains 1
    
por 08.03.2017 / 20:32