2
votes

Expressions régulières Python 0 ou plusieurs mots de l'ensemble

J'ai un gros bloc de texte dans lequel j'essaye de rechercher une phrase. La phrase peut être structurée de différentes manières.

  1. Je veux d'abord chercher un mot dans un ensemble de mots, appelons-le set 1.
  2. Après cela, il doit y avoir un espace ou une virgule (ou peut-être quelque chose sinon qui sépare les mots)
  3. Ensuite, il peut y avoir 0 ou plusieurs mots de l'ensemble 2
  4. Encore une fois suivi du mot caractères de séparation comme au point 2 ci-dessus
  5. enfin, il devrait y avoir un mot de l'ensemble 3

Idéalement, tous ces éléments devraient être dans la même phrase.

set 1 = (Potentiel | Capacité | Possibilité | besoin | nécessite | besoins | beaucoup | pour | Besoin | Obligatoire)

set 2 = (for|to|of|full|a|be|complete|Internal)

set 3 = (renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

J'ai donc cette expression regex p >

(Potential|Ability|Possibility|need|requires|needs|plenty|for|Needing|Requiring)[ ,]*(for|to|of|full|a|be|complete|Internal)[ ,]*(renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

Maintenant, cela correspondra à une phrase où il y a 0 ou 1 mot de l'ensemble 2 mais pas s'il y a des multiples. Par exemple, "offre une merveilleuse opportunité pour quelqu'un d'ajouter son propre cachet car la propriété a besoin d'une rénovation complète."

dès que j'ajoute 'a' avant 'complet', cela échoue. La même chose que si j'ajoute un autre «complet».

Comment spécifier de rechercher 0 ou plusieurs mots dans un ensemble?


0 commentaires

4 Réponses :


3
votes

Ensemble 1: correspond à l'un des mots de l'ensemble 1 avec un séparateur 1.

(Potential|Ability|Possibility|need|requires|needs|plenty|for|Needing|Requiring)[ ,]((for|to|of|full|a|be|complete|Internal)[ ,])*(renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

Ensemble 2: correspond à l'un des mots de l'ensemble 2 avec 1 séparateur, 0 fois ou plus.

/ p>

(renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

Ensemble 3: correspond à l'un des mots de l'ensemble 3

((for|to|of|full|a|be|complete|Internal)[ ,])*

Complet:

(Potential|Ability|Possibility|need|requires|needs|plenty|for|Needing|Requiring)[ ,]


4 commentaires

{1} est inutile.


J'ai couru ceci dans un testeur de regex en ligne qui est sorti find, mais j'ai juste essayé de l'exécuter dans un script python avec le 'import re text = "potential to modernize" regex = re.match ("((Potential | Capacité | Possibilité | besoin | nécessite | besoin | beaucoup | pour | Besoin‌ | Nécessaire) [] ((pour | à | de | plein | a | être | complet | Interne) []) * (rénover | améliorer | moderniser | moderniser | mettre à jour | rénover | ‌ améliorer | moderniser | moderniser | mettre à jour | potentiel | projet‌ | rénovation)) ", text) match = regex.groups () print (match) 'et I obtenir l'erreur ......


..... 'Traceback (dernier appel en dernier): Fichier "/Users/Charlie/Documents/python/regex_potential.py", ligne 5, dans match = regex.groups () AttributeError: objet' NoneType ' n'a pas d'attribut 'groupes' '


Sensibilité à la casse ... oups



2
votes

Longues alternatives dans les expressions régulières peut être assez lent . Je suggérerais d'adopter une autre approche. Commencez par segmenter le texte (divisé en mots) et l'itérer sur le tableau de mots en vérifiant si les ensembles suivants de 3 mots répondent à vos exigences

Quelque chose comme ça (plutôt un pseudocode qu'un vrai python):

def check(text):
  words = segment(text)
  for i in range(0, len(text)-2):
      check_word1(text[i]) and check_word1(text[i+1]) and check_word3(text[i+2])


1 commentaires

for i in range (0, len (text) -2): alors, puisque vous faites i + 2



0
votes

Au cas où vous ne le sauriez pas, vous pouvez utiliser des sites tels que https://regex101.com/ pour tester vos expressions régulières, et voir pourquoi ça marche / ça ne marche pas.

Dans ce cas, vous avez besoin du "zéro ou plus" ( * ) opérateur sur votre deuxième groupe. Le résultat serait:

(Potential|Ability|Possibility|need|requires|needs|plenty|for|Needing|Requiring)[ ,]*(?:(for|to|of|full|a|be|complete|Internal)[ ,]*)*(renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

Cependant, étant donné que vous voulez probablement que les mots soient séparés, incluez simplement l'espace sur l'opérateur (vous pouvez utiliser un groupe non capturant pour cela), ce qui donne:

XXX


2 commentaires

Cela correspondra à Potential , pouroffullabecompleteInternal, , fortooffullabecompleteInternalfortooffullabecompleteInternal‌ pourooffullabecomple‌ teInternalrenovate


Je sais, mais comme c'est ce qu'il a sur son regex, j'ai décidé de le modifier le moins possible (juste au cas où il voudrait ce comportement pour une raison quelconque)



1
votes

Vous devez utiliser cette expression régulière:

(Potential|Ability|Possibility|need|requires|needs|plenty|for|Needing|Requiring)[ ,](for|to|of|full|a|be|complete|Internal)*[ ,](renovate|improve|modernise|modernize|update|renovating|improving|modernising|modernizing|updating|potential|project|renovation)

Parce que vous avez un mot du premier ensemble. Après cela, vous avez un espace ou une virgule. Près de vous, il y a 0 mot ou plus de l'ensemble 2. Puis un autre espace ou virgule et enfin un mot du dernier ensemble.


0 commentaires