12
votes

Couper dans un motif à l'aide de Python Regex

objectif: J'essaie d'effectuer une coupe de python Regex où la scission ne fait pas tout à fait ce que je veux. J'ai besoin de couper dans un motif, mais entre les personnages.

ce que je recherche:

Je dois reconnaître le motif ci-dessous dans une chaîne et diviser la chaîne à l'emplacement du tuyau. Le tuyau n'est pas réellement dans la chaîne, il montre simplement où je veux diviser.

motif: cde | fg

chaîne: abcdefghijklmnocdefgzype

résultats: ['abcde', 'fghijklmnocde', 'fgzype']

ce que j'ai essayé:

Je semble que l'utilisation de la parenthèse avec parenthèse est proche, mais cela ne conserve pas le modèle de recherche attaché aux résultats comme j'en ai besoin.

re.split ('CDE () FG', 'ABCDEFGHIJKLMNOCDEFGZYPE')

donne,

['ab', 'hijklmno', 'zips']

Quand j'ai besoin,

['abcde', 'fghijklmnocde', 'fgzype']

Motivation:

pratiquer avec regex et voulait voir si je pouvais utiliser Regex pour créer un script qui prédire les fragments d'une digestion protéique à l'aide de protéases spécifiques.


6 commentaires

Une solution à base de non-regex est-elle acceptable pour vous?


Absolument! Cependant, j'allais pour l'élégance. Je peux le faire manuellement avec un paragraphe de code Python.


Ce dont vous avez besoin est une scission avec (? <= Cde) (? = Fg)


@sln ne recevriez-vous pas ['abcdefghijklmnocdefgzype'] en conséquence?


@Alecxe - Non, une position fractionnée est une pause où elle sépare le texte. (? <=) (? =) représente la pause.


Que diriez-vous d'utiliser re.findall (r ". +? (? <= Cde) (? = FG) |. + ", s)


4 Réponses :


5
votes

Vous pouvez le résoudre avec re.split () et positif " Regardez des circonstances ": xxx


Notez que si l'une des séquences coupées est une chaîne vide, vous obtiendrez une chaîne vide à l'intérieur de la liste résultante. Vous pouvez gérer cette "manuellement", échantillon (j'admets, ce n'est pas si joli): xxx

impression: xxx < / p>


6 commentaires

J'aime beaucoup cette solution, et cela fait ce que j'ai demandé, mais lorsque vous essayez de généraliser, je ne peux pas obtenir une séquence coupée comme celle-ci pour travailler | FGHI .


@MichaelMmolter Ouais, vous obtiendrez la chaîne vide supplémentaire comme premier élément divisé, non? Je crains que vous ayez à gérer le cas de délimiteurs de division vide comme | fhi ou fhi | trancher manuellement le résultat de re.split () :: [1:] et [: - 1] respectivement. Peut-être qu'il y a un moyen plus élégant de gérer cela..Merci.


Cette solution est tellement fausse: il va heureusement diviser "abcdexxxxxxxfr" en trois morceaux et pas divisé correctement s'il y a trois points de coupe corrects, etc.


@Alexis Eh bien, 3 points coupés..o-parcours, ce n'était pas dans la question de l'OP. Je peux casser cette solution facilement à tellement de façons et je ne prétends pas à fournir une solution universelle ici, je suis juste heureux d'être utile. Merci.


@alexce, n'êtes-vous pas un peu mal à la malveillance? Vous vous concentrez sur l'exemple trivial de l'OP et ignorez la description, ce qui indique clairement que CDE-FG est adjacent et qu'il existe un nombre indéterminé de scissions. Je m'attendais à ce que vous répariez ou supprimez la réponse, pas seulement les épaules.


@ALEXIS D'accord, je vois votre point et je suis prêt à améliorer la réponse. Pourriez-vous me fournir une chaîne d'échantillon qui correspondrait aux exigences de l'OP et où la solution fournie ne fonctionnerait pas? Merci.



8
votes

une manière non repensante serait de remplacer le motif avec la valeur de la tuyauterie et Alors Split . xxx


4 commentaires

Contrairement à la regex, cela vous permet de scinder facilement la corde sur de nombreux motifs différents. Cependant, il produira un résultat indésirable si le caractère de contrôle que vous introduisez est déjà utilisé dans le fichier. (Dans ce cas, le tuyau)


@Yab exactement. La réponse est une alternative plus rapide à la regex. Le PO mentionne qu'ils sont ouverts aux réponses non-regeures dans un commentaire et donc la réponse. Le tuyau est supposé ne pas être présent dans l'ensemble de données. Habituellement, dans de tels cas, un délimiteur multiple contenant des caractères spéciaux et des littéraux unicode sont utilisés. Je n'ai pas utilisé cela pour démontrer un cas d'utilisation simple.


Pour les cas où vous avez besoin a regexp, vous pouvez utiliser la même approche avec re.sub . Par exemple, re.sub (r "(CD [xy]) (FG)", r "\ 1 | \ 2", données) .


Oui, pour ce cas en particulier, nous pouvons utiliser re.sub (r "(CDE) (FG)", r "\ 1 | \ 2", s) .split ('|') .



1
votes

Une solution plus sûre non-regex pourrait être ceci: xxx

https: // reply .it / C448


0 commentaires

2
votes

Pour conserver le modèle de fractionnement lorsque vous vous séparez avec re.split ou des parties de celui-ci, joignez-les entre parenthèses. xxx

assez facile. Toutes les pièces sont là, mais comme vous pouvez le constater, ils ont été séparés. Nous devons donc les réassembler. C'est la partie délicate. Regardez prudemment et vous verrez que vous devez rejoindre les deux premières pièces, les deux dernières pièces et le reste en triples. Je simplifie le code en remplissant la liste, mais vous pouvez le faire avec la liste d'origine (et un autre code supplémentaire) si la performance est un problème. xxx

re.split () garantit une pièce pour chaque groupe de capture (parenthèse), plus une pièce pour ce qui est entre. Avec des expressions régulières plus complexes qui ont besoin de leur propre groupe, utilisez des groupes non capturants pour conserver le format des données retournées. (Sinon, vous devrez adapter l'étape de remontage.)

ps. J'aime aussi la suggestion de Bhargav Rao d'insérer un caractère de séparateur dans la chaîne. Si la performance n'est pas un problème, je suppose que c'est une question de goût.

edit: Voici une solution (moins transparente) de le faire sans ajouter de chaîne vide à la liste: xxx


0 commentaires