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?

Saisha
fonte
Uma quarta coluna? O que deve acontecer se essa coluna já estiver ocupada (segunda linha no seu exemplo) ou se as outras colunas estiverem vazias (última linha)?
Kusalananda
@Kusalananda Removido esse critério de minha consulta :)
Saisha
Em uma rápida olhada, todas as respostas contam os campos ou as sequências separadas por vírgula que correspondem ao Rv*padrão em qualquer lugar da linha, não apenas em uma coluna específica. Portanto, observarei que, se você realmente tiver outros dados no arquivo, não apresentados na pergunta aqui, pode ser necessário modificar as soluções adequadamente. (Ou esclarecer a questão.)
ilkkachu

Respostas:

10

Você simplesmente deseja adicionar uma coluna com a contagem de colunas nela. 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 awkvariável que contém o número de campos (colunas) no registro atual (linha). Imprimimos esse número seguido de uma vírgula e o restante da linha, para cada linha.

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

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

FSé o separador de campos awkusado para dividir cada registro em campos e o definimos como vírgula -F ','na linha de comando (como na primeira solução). OFSé o separador do campo de saída e definimos o mesmo para FSantes da leitura da primeira linha de entrada.

Kusalananda
fonte
5

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

 awk '{print gsub(/Rv[0-9]{4}c?/, "&"), $0}'
Stéphane Chazelas
fonte
4

Uma abordagem Perl:

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

As -amarcas perlse comportam como awke dividem cada linha de entrada na string fornecida por -Fe salve os campos resultantes na matriz @F. Portanto, $#Fserá o índice mais alto da matriz @Fe, como as matrizes começam a contar em 0, $#F+1será o número total de elementos na matriz. Os -pmeios "imprimem todas as linhas de entrada após a aplicação do script fornecido por -e. O s///operador de substituição e aqui estão substituindo o início da linha ( ^) pelo número de campos + 1 e vírgula ( $#F+1 . ",").

terdon
fonte
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 Rvsubstring 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 queremos torná-lo mais detalhado e incluir a possibilidade de que os genes não contenham a cadeia "Rv" (mas mantenha a suposição de que a coluna3 é uma cadeia de valor separada por vírgula), 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
Sergiy Kolodyazhnyy
fonte