2
votes

Python regex: correspond uniquement si le motif est répété n nombre de fois

J'ai une chaîne: Nom Masse De À Liaison disulfure -2.02 97 144 Liaison disulfure -2.02 111158 Liaison disulfure -2.02 121 174 Liaison disulfure -2.02 125 176 Liaison disulfure -2.02 85174 Liaison disulfure -2.02 10 176

Je veux extraire les tuples (97,144), (111,158), (121,174), (125,176), (85,174), (10,176) (c'est-à-dire les paires de nombres après -2,02 dans chaque cas ).

Je veux seulement faire correspondre les chaînes qui correspondent à ce nombre exact de motifs répétés (c'est-à-dire où le même motif de mot de 'Disulphide bond -2.02 XX' est répété exactement 6 fois). Il y aura d'autres chaînes dans le fichier avec exactement le même motif, mais répétées plus ou moins de 6 fois (par exemple, une autre chaîne dans le fichier pourrait être 'Name Mass From To Disulfide bond -2.02 97 144 Disulfide bond -2.02 111 158 Disulphide bond -2.02 121 174 ', je ne veux pas correspondre à ça).

Au départ, j'écrivais une regex comme celle-ci:

ix_regex = re.search(r' Disulphide bond  -2.02  ([\d]+)  ([\d]+)  ',mod_line)


3 commentaires

Voulez-vous dire qu'il doit y avoir 6 liaisons consécutives Disulfure X X X ou les correspondances peuvent-elles apparaître n'importe où dans la chaîne? Veuillez vérifier cette approche au cas où ils pourraient apparaître n'importe où dans la chaîne.


essayez Nom Masse De À (?: Liaison disulfure -2.02 ([\ d] +) ([\ d] +)) {6}


Consultez également ideone.com/P32pbg s'ils doivent être consécutifs.


3 Réponses :


2
votes

Vous avez la bonne idée avec le quantificateur {6} .

Votre problème n'est pas de grouper ( (? :) - groupe non sélectionné) le bon modèle.

Nom Masse De À (?: Liaison disulfure -2 \ .02 ([\ d] +) ([\ d] +) \ s *) {6} devrait faire l'affaire.

Explication

  • Nom de la masse de à - le début de la chaîne.
  • (?: - ouverture d'un groupe sans sélection.
  • Disulfure bond -2 \ .02 ([\ d] +) ([\ d] +) \ s * - le motif que vous voulez répéter
  • ) - ferme le groupe non sélectionné.
  • {6} - répétez le groupe sans sélection six fois.

0 commentaires

3
votes

Vous pouvez utiliser ce code en python:

>>> import re
>>> s = 'Name  Mass  From  To  Disulphide bond  -2.02  97  144  Disulphide bond  -2.02  111  158  Disulphide bond  -2.02  121  174  Disulphide bond  -2.02  125  176  Disulphide bond  -2.02  85  174  Disulphide bond  -2.02  10  176'
>>> arr = re.findall(r'(?<=Disulphide bond  -2.02  )(\d+)  (\d+)', s)
>>> if len(arr) == 6:
...     print arr
...
[('97', '144'), ('111', '158'), ('121', '174'), ('125', '176'), ('85', '174'), ('10', '176')]

Démo de code

** Détails RegEx: &&

  • (? : expression Lookbehind pour affirmer que nous avons donné une chaîne à gauche de la position actuelle
  • (\ d +) (\ d +) : Faites correspondre 2 nombres séparés par 2 espaces dans 2 groupes de capture différents


1 commentaires

Cela suppose que les correspondances peuvent apparaître n'importe où dans la chaîne, tout comme J'ai suggéré



1
votes

Si je comprends bien, vous pouvez utiliser

reg1 = re.compile(r"(?:\s?Disulphide bond  -2.02  [\d]+  [\d]+\s?){6}")
matches = reg1.findall(your_string)

reg2 = re.compile(r"Disulphide bond  -2.02  ([\d]+)  ([\d]+)")
pairs = [reg2.findall(el) for el in matches]

d’abord, vous faites correspondre toutes les instances où ce motif est répété exactement six fois, puis vous extrayez les paires de chaque instance

p >


0 commentaires