re.search - just skip it

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rasdj@frontiernet.net

    #1

    re.search - just skip it

    Input is this:

    SET1_S_W CHAR(1) NOT NULL,
    SET2_S_W CHAR(1) NOT NULL,
    SET3_S_W CHAR(1) NOT NULL,
    SET4_S_W CHAR(1) NOT NULL,
    ;

    ..py says:

    import re, string, sys
    s_ora = re.compile('.*S _W.*')
    lines = open("y.sql").r eadlines()
    for i in range(len(lines )):
    try:
    if s_ora.search(li nes[i]): del lines[i]
    except IndexError:
    open("z.sql","w ").writelines(l ines)

    but output is:

    SET2_S_W CHAR(1) NOT NULL,
    SET4_S_W CHAR(1) NOT NULL,
    ;

    It should delete every, not every other!

    thx,

    RasDJ

  • Duncan Booth

    #2
    Re: re.search - just skip it

    wrote:
    [color=blue]
    > Input is this:
    >
    > SET1_S_W CHAR(1) NOT NULL,
    > SET2_S_W CHAR(1) NOT NULL,
    > SET3_S_W CHAR(1) NOT NULL,
    > SET4_S_W CHAR(1) NOT NULL,
    > ;
    >
    > .py says:
    >
    > import re, string, sys
    > s_ora = re.compile('.*S _W.*')
    > lines = open("y.sql").r eadlines()
    > for i in range(len(lines )):
    > try:
    > if s_ora.search(li nes[i]): del lines[i]
    > except IndexError:
    > open("z.sql","w ").writelines(l ines)
    >
    > but output is:
    >
    > SET2_S_W CHAR(1) NOT NULL,
    > SET4_S_W CHAR(1) NOT NULL,
    > ;
    >
    > It should delete every, not every other![/color]

    No, it should delete every other line since that is what happens if you use
    an index to iterate over a list while deleting items from the same list.
    Whenever you delete an item the following items shuffle down and then you
    increment the loop counter which skips over the next item.

    The fact that you got an IndexError should have been some sort of clue that
    your code was going to go wrong.

    Try one of these:
    iterate backwards
    iterate over a copy of the list but delete from the original
    build a new list containing only those lines you want to keep

    also, the regex isn't needed here, and you should always close files when
    finished with them.

    Something like this should work (untested):

    s_ora = 'S_W'
    input = open("y.sql")
    try:
    lines = [ line for line in input if s_ora in line ]
    finally:
    input.close()

    output = open("z.sql","w ")
    try:
    output.write(st r.join('', lines))
    finally:
    output.close()

    Comment

    • Fredrik Lundh

      #3
      Re: re.search - just skip it

      <rasdj@frontier net.net> wrote:
      [color=blue]
      > but output is:
      >
      > SET2_S_W CHAR(1) NOT NULL,
      > SET4_S_W CHAR(1) NOT NULL,
      >
      > It should delete every, not every other![/color]

      for i in range(len(lines )):
      try:
      if s_ora.search(li nes[i]): del lines[i]
      except IndexError:
      ...

      when you loop over a range, the loop counter is incremented also if you delete
      items. but when you delete items, the item numbering changes, so you end up
      skipping over an item every time the RE matches.

      to get rid of all lines for which s_ora.search matches, try this

      lines = [line for line in lines if not s_ora.search(li ne)]

      for better performance, get rid of the leading and trailing ".*" parts of your
      pattern, btw. not that it matters much in this case (unless the SQL state-
      ment is really huge).

      </F>



      Comment

      • Kent Johnson

        #4
        Re: re.search - just skip it

        rasdj@frontiern et.net wrote:[color=blue]
        > Input is this:
        >
        > SET1_S_W CHAR(1) NOT NULL,
        > SET2_S_W CHAR(1) NOT NULL,
        > SET3_S_W CHAR(1) NOT NULL,
        > SET4_S_W CHAR(1) NOT NULL,
        > ;
        >
        > .py says:
        >
        > import re, string, sys
        > s_ora = re.compile('.*S _W.*')
        > lines = open("y.sql").r eadlines()
        > for i in range(len(lines )):
        > try:
        > if s_ora.search(li nes[i]): del lines[i][/color]

        When you delete for example lines[0], the indices of the following lines change. So the former
        lines[1] is now lines[0] and will not be checked.

        The simplest way to do this is with a list comprehension:
        lines = [ line for line in lines if not s_ora.search(li ne) ]

        Even better, there is no need to make the intermediate list of all lines, you can say
        lines = [ line for line in open("y.sql") if not s_ora.search(li ne) ]

        In Python 2.4 you don't have to make a list at all, you can just say
        open("z.sql","w ").writelines(l ine for line in open("y.sql") if not s_ora.search(li ne))

        ;)

        Kent
        [color=blue]
        > except IndexError:
        > open("z.sql","w ").writelines(l ines)
        >
        > but output is:
        >
        > SET2_S_W CHAR(1) NOT NULL,
        > SET4_S_W CHAR(1) NOT NULL,
        > ;
        >
        > It should delete every, not every other!
        >
        > thx,
        >
        > RasDJ
        >[/color]

        Comment

        Working...