7
votes

Python Regex pour correspondre au texte en guillemets simples, ignorant les devis échappés (et les onglets / Neuflines)

Compte tenu d'un fichier de texte, où le personnage que je veux correspondre est délimité par des guillemets simples, mais peut avoir zéro ou une citation unique évasée, ainsi que zéro ou plus d'onglets et de caractères de nouvelle ligne (non échappés) - i vouloir correspondre au texte uniquement. Exemple: xxx

Je veux saisir uniquement le texte (et les espaces), ignorer les onglets / nouvelles lignes - et je ne me soucie pas de si le devis échappé apparaît dans les résultats, aussi longtemps que Cela n'affecte pas la correspondance: xxx

J'ai géré à créer une regex qui presque est-elle gère les citations évasées, mais pas les nouvelles lignes: xxx

Il existe définitivement une tonne de questions d'expression régulières, mais la plupart utilisent Perl, et s'il y en a une qui fait ce que je veux, je ne pouvais pas Figurez-le :) Et depuis que j'utilise Python, je m'en fiche si elle est répandue sur plusieurs groupes, il est facile de les recombiner.

Certaines réponses ont dit simplement avec le code de l'analyse le texte. Bien que je suis sûr que je pourrait le faire - je suis tellement ferme avoir une regrette de travail :) et cela semble être devrait être être Datable.

Mise à jour: je viens de réaliser que je fais un python les readlines () pour obtenir chaque ligne, ce qui décourage évidemment les lignes qui se sont transmises à la regex. Je cherche la ré-écrivant, mais toutes les suggestions sur cette partie seraient également très utiles.


4 commentaires

Dupliqué possible de regex pour la gestion des caractères échappés pour des articles comme chaîne Littéraux


Pas si dupliqué - j'essaie de gérer (non-échappé) de nouvelles lignes qui rompent mes données d'entrée, également.


Je suis d'accord, mais je pensais que cela mérite d'être souligné de toute façon. Il suffit d'utiliser re.multiline ( docs.python.org /Library/re.html#re.multiline ) Pour correspondre à plusieurs lignes, $ pour ignorer / correspondre aux lignes d'endlines et \ s (même lien) pour correspondre Newspace. Allez, sauterelle;)


En tant que note latérale: la chaîne menu_item = 'dave \ s inférieure-connu \ n gyro'; ne contient pas de citation unique évasée. Le littéral à chaîne en contient un, mais c'est pour aider Python à la distinguer de la citation de bout en bout de chaîne. Si vous souhaitez des tests réelles avec des guillemets simples évasés, vous auriez besoin de quelque chose comme Ohai = 'Dave \\\' s '.


3 Réponses :


3
votes

Cela devrait le faire: xxx

ici the (?: [^ '\\] | \\') * partie correspond à une séquence de n'importe quel caractère Sauf ' et \ ou un \' . L'ancien expression [^ '\\] permet également des pauses de ligne et des tabulateurs que vous devez ensuite remplacer par un seul espace.


5 commentaires

Lorsque vous dites, "remplacez-vous un seul espace" - voulez-vous dire nettoyer / supprimer les onglets / les pauses de la ligne avant en cours d'exécution? Lorsque j'ai essayé votre re, cela ne correspondait à aucune des lignes avec des pauses.


@JOHN C: Non, je le ferais ensuite avec quelque chose comme re.sub (r "[\ n \ r \ t] +", correspondance) .


Cependant, ma variable de match m est vide pour les lignes d'entrée qui ont des pauses de ligne, il n'y a donc rien à substituer.


Arg! En regardant mon code, je fais une liste de réinscriptions () sur le fichier d'entrée - que je suppose enfreindre les nouvelles lignes. Apparemment, j'ai besoin de ré-écrire plus de mon code (soupir).


Il convient de noter que, si cette expression fonctionne pour des citations évasées, il sera également pas travail lorsqu'il rencontre une autre séquence d'évacuation comme \ n ou une barre oblique inverse. Vous devrez ajouter toutes les séquences d'échappement que vous attendez de rencontrer au groupe, c'est-à-dire: '(((?: [^' \\] | \\ | \\ r | \\ n | \\ t | \\\\ ') *)'



2
votes

Vous êtes froide, essayez-le comme ceci:

pattern = re.compile(r"menu_item = '(.*?)(?<!\\)'", re.DOTALL)


1 commentaires

A l'air intéressant, mais comme je l'ai noté dans un autre commentaire - je viens de réaliser que je fais des readlines , qui enfreint les nouvelles lignes, j'ai donc un autre problème à réparer.



14
votes

Ce script testé devrait faire le truc: xxx

Voici la version courte de la regex:

'([^' \\] * (?: \\. [^ '\\] * *) *)'

Cette regex est optimisée à l'aide de Jeffrey Friedl's "déroulant-la-boucle" efficacité technique. (Voir: 0 commentaires