Recherche avec grep

Résolu/Fermé
Bernard - Modifié le 10 nov. 2021 à 15:02
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 - 11 nov. 2021 à 10:28
Bonjour,

Je voudrais rechercher une chaîne de caractère précise dans un fichier
data.txt
.

Voici ce que j'ai. Le fichier
data.txt
contient une ligne de caractères ;
ACGGGACAGTGGTGACGCGGATCGACT


Je dois trouver ceci :
CGGGACAGTG
GGGACAGTGG
TGGTGACGCG
CGGATCGACT


J'ai essayé avec
grep -o -e ".GG......." data.txt
, ça ne me donne pas le résultat voulu.

CGGGACAGTG
CGGATCGACT

5 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 11 nov. 2021 à 01:36
Bonjour,

Effectivement, il manque deux lignes car
grep
cherche de manière gloutonne, et les deux lignes manquantes sont recouvertes par les deux lignes affichées par
grep
. Je n'ai pas vu d'option dans grep qui permettent de changer ce comportement mais tu peux vérifier dans
man grep
.

Le problème que tu soulèves est traité dans cette discussion avec d'autres outils comme
awk
ou
python
.

Ton problème ne nécessite pas d'expression rationnelle, donc on peut s'en sortir en énumérant tous les slices de 10 caractères tels que le 2nd et le 3ème caractères sont
GG
, ce qui donne :

data.txt

ACGGGACAGTGGTGACGCGGATCGACT


toto.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys     

def find_occurrences(s):
    return (
        s[i:i+10]
        for i in range(len(s))
        if s[i:i+10][1:3] == "GG"
    )

with open(sys.argv[1]) as f:
    for line in f.readlines(): 
        line = line.strip()
        print("\n".join(
            occurence
            for occurence in find_occurrences(line)
        ))


Quelques explications :
  • en Python,
    s[i:j]
    la sous-chaîne de
    s
    allant de l'index
    i
    (inclu) à l'index
    j
    (exclu) (on parle de slicing) ;
  • s[i:i+10]
    permet donc d'extraire les 10 caractères glissants de
    s
    en partant de l'index
    i
    ;
  • par rapport à ton critère de filtrage, on veut contrôler le second et le troisième caractères sont "GG", et comme les caractères sont indexés à partir de 0, cela correspond au slice
    [1:3]
    , soit au final
    s[i:i+10][1:3]
    ;
  • la fonction
    find_occurrences
    retourne un itérateur sur une chaîne
    s
    arbitraire (en l'occurrence,
    ACGGGACAGTGGTGACGCGGATCGACT
    ) de sorte à extraire les slices de taille 10 dont second et le troisième caractères sont "GG" ;
  • cette fonction est appelée pour chaque ligne du fichier
    data.txt
    (le chemin vers le fichier est récupéré en paramètre du programme via
    sys.argv[1]
    ) ; les résultats sont concaténés par le caractère
    "\n"
    (retour à la ligne) de sorte à afficher un résultat par ligne ;
  • si tu n'es pas familier de Python et un peu surpris par la position des
    for
    ), c'est parce qu'on utilise un concept propre à python (voir les listes de compréhensions).


Résultat

(mando@silk) (~) $ python3 toto.py data.txt
CGGGACAGTG
GGGACAGTGG
TGGTGACGCG
CGGATCGACT


Bonne chance
1
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
10 nov. 2021 à 17:59
hello
$ awk -F ""  '{for (x=1; x<=NF; x++)if ($x=="G" && $(x+1)=="G"){printf $(x-1)$x; for (n=1;n<9;n++)printf $(x+n); print ""}}' data.txt
CGGGACAGTG
GGGACAGTGG
TGGTGACGCG
CGGATCGACT
1
Bonjour Mamiemando,

Merci pour ta réponse rapide, j'ai effectivement regardé dans le
man
de
grep
, je n'ai rien trouvé. J'ai essayé avec
awk
combiné avec
sed
rien non plus. je vais essayer ton script en python et reviens vers toi.
0
Bonjour Dubcek,

effectivement, ca fonctionne aussi, merci beaucoup.
Merci à tous les deux pour votre aide.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
Modifié le 11 nov. 2021 à 10:28
plus court
$ awk '{for (x=1; x<=length(); x++)if (substr($0, x, 2)=="GG")print substr($0, x-1, 10)}' data.txt
CGGGACAGTG
GGGACAGTGG
TGGTGACGCG
CGGATCGACT
0