Actively searching with Regular Expressions

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jlm699
    Contributor
    • Jul 2007
    • 314

    Actively searching with Regular Expressions

    I have an application that is build on wxPython and have run into a small but annoying problem. I use a Search Control in my toolbar just as in the ToolBar example. Now when the user enters say PrmID[ ... this gets passed to a regular expression search function, however this obviously raises the exception saying that there is an unexpected end to the regular expression. What I would like to do is replace '[' with '\[', however using the string.replace function yields 'PrmID\\[' (escaping the escape character, but not the character I would like to have escaped). My code of what I've tried is as follows:

    Code:
       def OnTextEntered(self, evt):
            text = self.GetValue()
            if re.search('\[', text) and not re.search('\]', text):
                text.replace('[', '\[')
            if self.DoSearch(text, evt):
                if text not in self.searches:
                    self.searches.append(text)
                    if len(self.searches) > self.maxSearches:
                        del self.searches[0]
                    self.SetMenu(self.MakeMenu())
    And the doSearch function...
    Code:
        def DoSearch(self,  text, event=None):
            if not len(self.data_bak):
                return False
    
            # 10014 is the Event type for wx.EVT_MENU
            # 10164 is the Event type for wx.EVT_TEXT (adaptive search)
            # 10165 is the Event type for wx.EVT_TEXT_ENTER
            valid_events = [10014, 10165]
            
            regex = re.compile(text.upper())
            tool = self.tb.FindById(Global.OnTB_ActSearch_Id)
            if tool.IsToggled():
                self.lc.DeleteAllItems()
                for entry in range(len(self.data_bak)):
                    if text:
                        if regex.search(self.data_bak[entry][0].upper()):
                            self.lc.Append(self.data_bak[entry])
                    else:
                        self.lc.Append(self.data_bak[entry])
                return False
            elif not tool.IsToggled() and event.GetEventType() in valid_events:
                idx = self.lc.FindItem(self.currentItem + 1, text, True)
                if idx != -1:
                    self.lc.Focus(idx)
                    self.lc.Select(idx)
                return True
    BTW, basically this application has a listing of Parameter names and values in a ListControl (self.lc), which when initially opened is backed-up by a two-dimensional array (self.data_bak) .
    This 'active search' will modify what the user sees in the listctrl (making sure to update the back-up as well), just as they type it (I wanted to reproduce the Search function from the upper right corner of iTunes). The toggle check is there because the user has a toggle button on the toolbar to turn this active search on or off.
    So if anybody has any ideas as to how to replace '[' in a string with literally '\[' I would appreciate it. I've played around with raw strings and even tried using a crazy combination of raw strings and the repr function to no avail.

    An example of parameter names is P_SWID_PrmID[0].

    To reiterate, I simply need to take the user input and escape any bracket characters so that the regex.search function does not mistake it for the start/end of a regular expression character class.
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    I'm not too familiar with regular expressions yet, but how 'buot making a character class of one character? re doesn't mind the the syntax of this pattern:
    [CODE=python]import re
    >>> s = 'PrmID['
    >>> re.sub('[[]', '[', s)
    'PrmID['
    >>> [/CODE]

    So, it seems that you could use:[CODE=python]s.replace('[', '[[]')[/CODE]

    Comment

    • bvdet
      Recognized Expert Specialist
      • Oct 2006
      • 2851

      #3
      Originally posted by bartonc
      I'm not too familiar with regular expressions yet, but how 'buot making a character class of one character? re doesn't mind the the syntax of this pattern:
      [CODE=python]import re
      >>> s = 'PrmID['
      >>> re.sub('[[]', '[', s)
      'PrmID['
      >>> [/CODE]

      So, it seems that you could use:[CODE=python]s.replace('[', '[[]')[/CODE]
      Good point Barton. I checked it out also:[code=Python]>>> s = 'P_SWID_PrmID[0]'
      >>> searchStr = 'Prmid['
      >>> import re
      >>> patt = re.compile(sear chStr.replace('[', '[[]'), re.IGNORECASE)
      >>> m = patt.search(s)
      >>> m
      <_sre.SRE_Mat ch object at 0x00D5A9C0>
      >>> patt = re.compile(sear chStr, re.IGNORECASE)
      Traceback (most recent call last):
      File "<interacti ve input>", line 1, in ?
      File "C:\Python23\li b\sre.py", line 179, in compile
      return _compile(patter n, flags)
      File "C:\Python23\li b\sre.py", line 230, in _compile
      raise error, v # invalid expression
      error: unexpected end of regular expression
      >>> patt.findall(s)
      ['PrmID[']
      >>> [/code]

      Comment

      • jlm699
        Contributor
        • Jul 2007
        • 314

        #4
        Wow, thanks guys! That's elegant yet so simple! I was lazy and just replaced every occurance of '[' or ']' with '.' (I figured, if the user knows that much of the name they'll know the number contained within the brackets so actually finding a match to the bracket wasn't too terribly important)

        But thanks for the great suggestions!

        Comment

        Working...