2010-05-03 24 views
2
tickettypepat = (r'MIS Notes:.*(//p//)?.*') 
retype = re.search(tickettypepat,line) 
if retype: 
    print retype.group(0) 
    print retype.group(1) 

Étant donné l'entrée.Échec de la correspondance optionnelle Regex en cas de panne python

MIS Notes: //p// 

Quelqu'un peut-il me dire pourquoi le groupe (0) est

MIS Notes: //p// 

et le groupe (1) revient sur Aucun?

À l'origine, j'utilisais regex parce que, avant de rencontrer des problèmes, la correspondance était plus complexe que la simple correspondance // p // voici le code complet. Je suis assez nouveau à ce sujet, alors pardonnez mon noobness, je suis sûr qu'il y a de meilleures façons d'accomplir une grande partie de cela et si quelqu'un a envie de les signaler, ce serait génial. Mais mis à part le problème avec la regex pour // [pewPEW] // étant trop gourmand il semble être fonctionnel. J'apprécie l'aide.


Prend le texte et nettoie/convertit certaines choses.

filename = (r'.\4-12_4-26.txt') 
import re 
import sys 
#Clean up output from the web to ensure that you have one catagory per line 
f = open(filename) 
w = open('cleantext.txt','w') 

origdatepat = (r'(Ticket Date:)([0-9]+/[0-9]+/[0-9]+),([0-9]+:[0-9]+ [PA]M)') 
tickettypepat = (r'MIS Notes:.*(//[pewPEW]//)?.*') 

print 'Begining Blank Line Removal' 
for line in f: 
    redate = re.search(origdatepat,line) 
    retype = re.search(tickettypepat,line) 
    if line == ' \n': 
     line = '' 
     print 'Removing blank Line' 
#remove ',' from time and date line  
    elif redate: 
     line = redate.group(1) + redate.group(2)+ redate.group(3)+'\n' 
     print 'Redating... ' + line 

    elif retype: 
     print retype.group(0) 
     print retype.group(1) 

     if retype.group(1) == '//p//': 
      line = line + 'Type: Phone\n' 
      print 'Setting type for... ' + line 
     elif retype.group(1) == '//e//': 
      line = line + 'Type: Email\n' 
      print 'Setting type for... ' + line 
     elif retype.group(1) == '//w//': 
      line = line + 'Type: Walk-in\n' 
      print 'Setting type for... ' + line 
     elif retype.group(1) == ('' or None): 
      line = line + 'Type: Ticket\n' 
      print 'Setting type for... ' + line 

    w.write(line) 

print 'Closing Files'     
f.close() 
w.close() 

Et voici quelques entrée de l'échantillon.

Ticket No.: 20100426132 
Ticket Date: 04/26/10, 10:22 AM 
Close Date: 
Primary User: XXX 
Branch: XXX 
Help Tech: XXX 
Status: Pending 
Priority: Medium 
Application: xxx 
Description: some issue 
Resolution: some resolution 
MIS Notes: some random stuff //p// followed by more stuff 
Key Words: 

Ticket No.: 20100426132 
Ticket Date: 04/26/10, 10:22 AM 
Close Date: 
Primary User: XXX 
Branch: XXX 
Help Tech: XXX 
Status: Pending 
Priority: Medium 
Application: xxx 
Description: some issue 
Resolution: some resolution 
MIS Notes: //p// 
Key Words: 

Ticket No.: 20100426132 
Ticket Date: 04/26/10, 10:22 AM 
Close Date: 
Primary User: XXX 
Branch: XXX 
Help Tech: XXX 
Status: Pending 
Priority: Medium 
Application: xxx 
Description: some issue 
Resolution: some resolution 
MIS Notes: //e// stuff.... 
Key Words: 


Ticket No.: 20100426132 
Ticket Date: 04/26/10, 10:22 AM 
Close Date: 
Primary User: XXX 
Branch: XXX 
Help Tech: XXX 
Status: Pending 
Priority: Medium 
Application: xxx 
Description: some issue 
Resolution: some resolution 
MIS Notes: 
Key Words: 

Répondre

4

MIS Notes:.*(//p//)?.* fonctionne comme celui-ci, sur l'exemple de "MIS Notes: //p//" comme cible:

  1. MIS Notes: matchs "MIS Notes:", pas de surprises ici.
  2. .* exécute immédiatement à la fin de la chaîne (correspondent à ce jour "MIS Notes: //p//")
  3. (//p//)? est facultative. Rien ne se passe.
  4. .* n'a plus rien à faire correspondre, nous sommes déjà à la fin de la chaîne. Puisque l'étoile autorise zéro correspondance pour l'atome précédent, le moteur regex arrête de rapporter la chaîne entière comme une correspondance, et le sous-groupe comme vide.

Maintenant, lorsque vous modifiez la regex à MIS Notes:.*(//p//).*, le comportement change:

  1. MIS Notes: matchs "MIS Notes:", toujours pas de surprises ici.
  2. .* exécute immédiatement à la fin de la chaîne (correspondent à ce jour "MIS Notes: //p//")
  3. (//p//) est nécessaire. Le moteur commence à faire marche arrière caractère par caractère afin de répondre à cette exigence. (Match jusqu'ici "MIS Notes: ")
  4. (//p//) peut correspondre. Le sous-groupe un est enregistré et contient "//p//".
  5. .* s'exécute jusqu'à la fin de la chaîne. Astuce: Si vous n'êtes pas intéressé par ce qu'il correspond, il est superflu et vous pouvez l'enlever.

Maintenant, lorsque vous modifiez la regex à MIS Notes:.*?//(p)//, le comportement change à nouveau:

  1. MIS Notes: correspond "MIS Notes:", et toujours pas de surprises ici.
  2. .*? est non gourmand et vérifie l'atome suivant avant de procéder (le match jusqu'à présent "MIS Notes: ")
  3. //(p)// peut égaler. Le sous-groupe un est enregistré et contient "p".
  4. Terminé. Notez qu'il n'y a pas de retour en arrière, cela fait gagner du temps.

Maintenant, si vous savez qu'il ne peut pas / avant la //p//, vous pouvez utiliser: MIS Notes:[^/]*//(p)//:

  1. MIS Notes: matchs "MIS Notes:", vous voyez l'idée.
  2. [^/]* peut effectuer une avance rapide à la première barre oblique (ce qui est plus rapide que .*?)
  3. //(p)// ne peut égaler. Le sous-groupe un est enregistré et contient "p".
  4. Terminé. Notez qu'il n'y a pas de retour en arrière, cela fait gagner du temps. Cela devrait être plus rapide que la version # 3.
+0

Merci pour l'explication approfondie, je pense que je comprends maintenant, je dois courir à une réunion pour un tic, mais au retour va tester. – AaronG

+0

Je l'ai essayé et je pense que nous sommes proches MIS Notes:. *? (// [pewPEW]) correspond à tous les cas où il y a une balise // * // quelconque. Mais il casse elif retype.group (1) == ('' ou None): line = line + 'Type: Ticket \ n' print 'Type de paramètre pour ...' + ligne Attendu que MIS Notes:. *? (// [pewPEW ] //)? semble donner null pour le groupe (1), peu importe quoi. Même chose avec MIS Notes:. *? (// [pewPEW] //) * – AaronG

+0

J'ai évidemment manqué le // suivant dans mon premier exemple dans le dernier commentaire. Vous auriez dû lire, Notes MIS:. *? (// [pewPEW] //) – AaronG

1

Regex sont avides, ce qui signifie que .* matchs autant que possible, la chaîne entière. Il n'y a donc plus rien à faire correspondre au groupe optionnel. group(0) est toujours la totalité de la piqûre correspondante.

De votre commentaire, pourquoi avez-vous besoin de regex? Est-ce pas quelque chose comme ça assez:

if line.startswith('MIS Notes:'): # starts with that string 
    data = line[len('MIS Notes:'):] # the rest in the interesting part 
    if '//p//' in data: 
     stuff, sep, rest = data.partition('//p//') # or sothing like that 
    else: 
     pass #other stuff 
+0

Merci pour le commentaire rapide en fin de compte, je suis en train de faire correspondre une chaîne qui a le motif Remarques MIS: + rien ou rien avant la chaîne // p // et tout ou rien après. et naturellement // p // est optionnel aussi. Donc je suppose que j'ai besoin d'un moyen d'éviter la gourmandise du début. Désolé si cette description n'est pas assez claire faites le moi savoir et je peux essayer de clarifier. – AaronG

+0

Question éditée pour essayer et clarifier le raisonnement de but/regex. Merci. – AaronG

0

Le motif est ambiguë selon vos besoins. Il serait bon de les regrouper par préfixe ou suffixe. Dans l'exemple ici, j'ai choisi le groupement de préfixes. Fondamentalement, si //p// se produit dans la ligne, le préfixe est non vide. Suffixe sera tout après l'article //p//, ou tout dans la ligne si elle n'existe pas.

import re 
lines = ['MIS Notes: //p//', 
    'MIS Notes: prefix//p//suffix'] 

tickettypepat = (r'MIS Notes: (?:(.*)//p//)?(.*)') 
for line in lines: 
    m = re.search(tickettypepat,line) 
    print 'line:', line 
    if m: print 'groups:', m.groups() 
    else: print 'groups:', m 

résultats:

line: MIS Notes: //p// 
groups: ('', '') 
line: MIS Notes: prefix//p//suffix 
groups: ('prefix', 'suffix') 
+0

À moins que je ne comprenne mal votre solution, je ne suis pas sûr que cela fasse ce que je veux. Idéalement, la regex retournerait toujours // p // // e // ou // w // dans un groupe spécifique s'il était présent dans l'entrée. – AaronG