Extracting parts of string between anchor points

Cameron Simpson cs at zip.com.au
Thu Feb 27 22:40:12 CET 2014

On 27Feb2014 20:07, Jignesh Sutar <jsutar at gmail.com> wrote:
> I've kind of got this working but my code is very ugly. I'm sure it's
> regular expression I need to achieve this more but not very familiar with
> use regex, particularly retaining part of the string that is being
> searched/matched for.

Regexps are quite useful for very variable text. You're just splitting
on ':' and '-:-', which is very easy and does not need a regexp.
Avoid regexps if the code can be written easily and readably without
them; they are cryptic and fragile.

> Notes and code below to demonstrate what I am trying to achieve. Any help,
> much appreciated.
> Examples=["Test1A",
>                   "Test2A: Test2B",
>                    "Test3A: Test3B -:- Test3C", ""]

Minor remark. Class names tend to have leading uppercase names,
like Foo. ordinary variables tend to have lower case names, like
foo. A habit to get into - it maes your code more readable for
everyone else.

Code suggestions below the code...

> # Out1 is just itself unless if it is empty
> # Out2 is everything left of ":" (including ":" i.e. part A) and right of
> "-:-" (excluding "-:-" i.e. part C)
>     # If text doesn't contain "-:-" then return text itself as it is
> # Out3 is everything right of "-:-" (excluding "-:-" i.e. part C)
>    # If text doesn't contain "-:-" but does contains ":" then return part B
> only
>    # If it doesn't contain ":" then return itself (unless if it empty then
> "None")
> for i,s in enumerate(Examples,start=1):
>     Out1=s if len(s)>0 else "Empty"
>     Out2=s[:s.find(":")+3] + s[s.find("-:-")+5:] if s.find("-:-")>0 else
> s.strip() if len(s) else "Empty"
>     Out3=s[s.find("-:-")+4:] if s.find("-:-")>0 else
> s[s.find(":")+1:].strip() if s.find(":")>0 and len(s)!=s.find(":")+1 else s
> if len(s) else "Empty"
>     print "Item%(i)s <%(s)s>  Out1 = %(Out1)s" % locals()
>     print "Item%(i)s <%(s)s>  Out2 = %(Out2)s" % locals()
>     print "Item%(i)s <%(s)s>  Out3 = %(Out3)s" % locals()

I would be parsing the string using "split", progressively.

Example (completely untested):

  # initialise all parts because we will only set the parts
  # below if they appear in the text
  out1, out2, out3 = '', '', ''

  words = s.split(':', 1)
  if words: # arrays are false if empty, true if non-empty
    out1 = words.pop(0)
    # there is a second part - split it on "-:-"
    if words:
      words = words[0].split('-:-', 1)
      out2 = words.pop(0)
      if words:
        out3 = words.pop(0)

  # personally I would leave out1 etc as empty strings and only _print_ the word "Empty"
  # but if you really want to mangle the variables themselves:
  if not out1:
    out1 = "Empty"
  if not out2:
    out2 = "Empty"
  if not out3:
    out3 = "Empty"

Notice that by using split we do not need to do any funny string
index arithmetic.

Cameron Simpson <cs at zip.com.au>

You can't have everything...  where would you put it?
        - Charles Robinson, cr0100 at medtronic.com

More information about the Python-list mailing list