Comment compter l'occurrence d'un motif dans une ligne


8

J'ai un fichier qui comporte trois colonnes. La colonne 3 contient les noms des gènes et ressemble à ceci:

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

Comment puis-je imprimer le nombre de gènes dans chaque ligne?


Une quatrième colonne? Que doit-il se passer si cette colonne est déjà occupée (deuxième ligne dans votre exemple), ou si les autres colonnes sont vides (dernière ligne)?
Kusalananda

@Kusalananda Supprimé ce critère de ma requête :)
Saisha

D'un coup d'œil, toutes les réponses comptent les champs ou chaînes séparés par des virgules correspondant au Rv*modèle n'importe où sur la ligne et pas seulement dans une colonne particulière. Je vais donc simplement noter que si vous avez réellement d'autres données dans le fichier, non présentées dans la question ici, vous devrez peut-être modifier les solutions en conséquence. (Ou clarifiez la question.)
ilkkachu

Réponses:


10

Vous voulez simplement ajouter une colonne avec le nombre de colonnes qu'elle contient. Cela peut être fait en utilisant awk:

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

NFest une awkvariable contenant le nombre de champs (colonnes) dans l'enregistrement en cours (ligne). Nous imprimons ce numéro suivi d'une virgule et du reste de la ligne, pour chaque ligne.

Une alternative (même résultat, mais peut sembler un peu plus propre):

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

FSest le séparateur de champs qui awkutilise pour diviser chaque enregistrement en champs, et nous le définissons sur une virgule -F ','sur la ligne de commande (comme dans la première solution). OFSest le séparateur de champ de sortie , et nous le définissons comme FSavant la lecture de la première ligne d'entrée.


5

Si vous vouliez compter le nombre d'occurrences du Rv[0-9]{4}c?modèle par opposition au nombre de champs délimités par des virgules comme le suggère le sujet de votre question, vous pouvez faire:

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

4

Une approche Perl:

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

Les -amarques perlse comportent comme awket divisent chaque ligne d'entrée sur la chaîne donnée par -Fet enregistrent les champs résultants dans le tableau @F. Par conséquent, $#Fsera l'indice de tableau le plus élevé @Fet, puisque les tableaux commencent à compter 0, $#F+1sera le nombre total d'éléments dans le tableau. Le -pmoyen "imprime chaque ligne d'entrée après avoir appliqué le script donné par -e. C'est s///l'opérateur de substitution et ici, nous remplaçons le début de la ligne ( ^) par le nombre de champs + 1 et une virgule ( $#F+1 . ",").


1

Votre question indique que la colonne 3 contient les noms des gènes. Je suppose que votre entrée réelle est la suivante:

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

Chaque nom de gène dans la colonne 3 contient la Rvsous-chaîne principale . Ainsi, nous pouvons les compter en python comme suit:

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

La liste résultante montre le nombre de gènes dans chaque ligne, dans leur ordre respectif. Si nous voulons le rendre plus verbeux et inclure la possibilité que les gènes ne contiennent pas de chaîne "Rv" (mais gardons l'hypothèse que la colonne3 est une chaîne de valeur séparée par des virgules), nous pouvons également faire ce qui suit:

#!/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))

Essai:

$ ./count_genes.py input.txt                                                                                             
Line 0 contains 3
Line 1 contains 4
Line 2 contains 1
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.