jrwaller
jrwaller

Reputation: 51

How to write lines to a new file except for a specific block of text?

I am opening a text file, searching to find a specific line(writing previous lines to a new file). Once that line ("BASE CASE") is found, I want to search for a specific block of text to delete form a file.

I have constructed some code through researching similar problems online. Right now, it only creates an empty new eve file. It also gives me an error that "this file is being used in python" when I try to delete the blank files. An example of what the old file looks like would be this: There can be an unknown number of monitors for each block.

xxxoijasdf
Monitor 4
aowijefoi
BASE CASE

Monitor 5
Monitor 3
Monitor 2
Item 1 Item 2
End

Monitor 3
Monitor 4
Item 3 Item 4
End

Monitor 1
Item 5 Item 6
End

The code I currently have is:

    longStr1 = (r"C:\Users\jrwaller\Documents\Automated Eve\NewTest.txt")
    endfile1 = (r"C:\Users\jrwaller\Documents\Automated Eve\did we do it yet.txt")

    search_item = "Item 3 Item 4"

    with open(longStr1, "r") as f:
        with open(endfile1, "w") as new_file:
            lines = f.readlines()
            i=0
            while i < 2000:
                for line in f:
                    if lines[i] != 'BASE CASE':
                        new_file.write(lines[i])
                    else:
                        new_file.write(lines[i])
                        newfile.write(lines[i+1])
                        block = ''
                        for line in f:
                            if block:
                                block += line
                                if line.strip() == 'End':
                                    if search_item not in block: new_file.write(block + '\n')
                                    block = ''
                            elif line.startswith('Monitor'):
                                block = line
        new_file.close()
    f.close()

I am hoping to reprint the old txt file to the new file while deleting the block of text between the first 'End' and 'Monitor 1'. Current problems include the output file being blank and the output file being left open in python.

Upvotes: 0

Views: 91

Answers (2)

jrwaller
jrwaller

Reputation: 51

longStr1 = (r"C:\Users\jrwaller\Documents\Automated Eve\NewTest.txt")
endfile1 = (r"C:\Users\jrwaller\Documents\Automated Eve\did we do it yet.txt")

search_item = "Item 3 Item 4"

with open(longStr1, "r") as f:
    with open(endfile1, "w+") as new_file:
        state = 1
        write_out = True
        for line in f:
            if state == 1:
                write_out = True
                if "BASE CASE" in line:
                    state = 2
            elif state == 2:
                if line == '\n':
                    write_out = True
                    state = 3
            elif state == 3:
                write_out = True
                block = ''
                for line in f:
                    if block:
                        block += line
                        if line.strip() == 'End':
                            if search_item not in block: new_file.write(block + '\n')
                            block = ''
                    elif line.startswith('Monitor'):
                        block = line
                if search_item in line:
                    state = 4 
                    write_out = False
            elif state == 4:
                write_out = False
                if "End" in line:
                    state = 5    
                    write_out = False
            elif state == 5:              
                if "Monitor" in line:
                    write_out = True
                    state = 6                  
            elif state == 6:
                write_out = True
            if write_out:
                new_file.write(line)
f.close()
new_file.close()

Upvotes: 1

Prune
Prune

Reputation: 77850

You are describing a simple state machine. Your states are:

  1. initial state -- write lines to new file
  2. found "BASE CASE" -- write lines to new file
  3. found "End" -- do nothing
  4. this line is "Monitor 1" -- write lines to new file
  5. later, to EOF -- write lines to new file

Since there are only two actions ("write" and "don't write"), you can handle this with a state variable and an action flag. Something like this:

state = 1
write_out = True
for line in f:
    # Looking for "BASE CASE"; write line until then
    if state == 1:
        if "BASE CASE" in line:
            state = 2

    # Look for start of unwanted block
    elif state == 2:
        if "End" in line:
            state = 3
            write_out = False

    # Look for end of unwanted block
        ...

    # Acknowledge moving past "Monitor 1"
        ...

    # Iterate through rest of file
        ...

    if write_out:
        new_file.write(line)

If you prefer, you can write this as a sequence of implicit-state loops:

while not "BASE CASE" in line:
    new_file.write(line)
    line = f.readline()

while not "End" in line:
    new_file.write(line)
    line = f.readline()

while not "Monitor 1" in line:
    # Don't write this block to the output
    line = f.readline()

...

Can you take it from there?

Upvotes: 1

Related Questions