Additional match in Regex in python fails

tickettypepat = (r'MIS Notes:.*(//p//)?.*')
retype = re.search(tickettypepat,line)
if retype:
  print retype.group(0)
  print retype.group(1)

      

Given the input.

MIS Notes: //p//

      

Can anyone tell me why group (0)

MIS Notes: //p// 

      

and group (1) is returned as None?

I originally used regex because, before I ran into problems, the match was more complex than just matching // p // here for the complete code. I'm new to this, so forgive my noob, I'm sure there are better ways to accomplish most of this, and if anyone would like to point out that would be awesome. But besides the problem with the regex for // [pewPEW] // being too greedy, it seems to be functional. I appreciate the help.


Accepts text and cleans / converts some stuff.

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()

      


And here are some examples of input.

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:  

      

+2


a source to share


3 answers


MIS Notes:.*(//p//)?.*

works like the example "MIS Notes: //p//"

as a target:

  • MIS Notes:

    corresponds "MIS Notes:"

    , there are no surprises here.
  • .*

    runs immediately to the end of the line (so far "MIS Notes: //p//"

    )
  • (//p//)?

    is optional. Nothing happens.
  • .*

    there is nothing left to match, we are already at the end of the line. Because the star allows null matches for the preceding atom, the regex engine stops passing the entire string as a match, and the subgroup as empty.

Now when you change the regex to MIS Notes:.*(//p//).*

, the behavior changes:

  • MIS Notes:

    corresponds "MIS Notes:"

    , there are no surprises here.
  • .*

    runs immediately to the end of the line (so far "MIS Notes: //p//"

    )
  • (//p//)

    necessary. To fulfill this requirement, the engine begins to return a character by character. (Coincidence so far "MIS Notes: "

    )
  • (//p//)

    may match. Subgroup one is preserved and contains "//p//"

    .
  • .*

    runs to the end of the line. Hint: If you are not interested in what it matches, it is overkill and you can delete it.


Now when you change the regex to MIS Notes:.*?//(p)//

, the behavior changes again:

  • MIS Notes:

    matches "MIS Notes:"

    , and there are no surprises here.
  • .*?

    is not greedy and checks the next atom before continuing it (so far "MIS Notes: "

    )
  • //(p)//

    may match. Subgroup one is preserved and contains "p"

    .
  • Done. Please note that there is no tracking back, this saves time.

Now, if you know that the front //p//

cannot be /

, you can use MIS Notes:[^/]*//(p)//

::

  • MIS Notes:

    fits "MIS Notes:"

    , you get the idea.
  • [^/]*

    can go forward to the first forward slash (this is faster than .*?

    )
  • //(p)//

    may match. Subgroup one is preserved and contains "p"

    .
  • Done. Please note that no refunds are made, this saves time. It should be faster than version # 3.
+4


a source


Regex are greedy, which means it .*

matches as much as it can on the entire string. Thus, there is no additional information for the additional group. group(0)

- it's always all the agreed sting.

From you to comment why you need a regex event? Isn't that enough:



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

      

+1


a source


The pattern is ambiguous for your purposes. It would be convenient to group them using a prefix or suffix. In the example here, I have selected the prefix grouping. Basically, if //p//

it occurs in a string, then the prefix is ​​not empty. The suffix will be everything after the element, //p//

or everything in the string if it doesn't exist.

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

      

results:

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

      

0


a source







All Articles