Prox
Prox

Reputation: 759

How to replace a string in a file?

I have 2 numbers in two similar files. There is a new.txt and original.txt. They both have the same string in them except for a number. The new.txt has a string that says boothNumber="3". The original.txt has a string that says boothNumber="1".

I want to be able to read the new.txt, pick the number 3 out of it and replace the number 1 in original.txt.

Any suggestions? Here is what I am trying.

import re  # used to replace string
import sys # some of these are use for other code in my program

def readconfig():
    with open("new.text") as f:
        with open("original.txt", "w") as f1:
            for line in f:
                match = re.search(r'(?<=boothNumber=")\d+', line)
                for line in f1:
                    pattern = re.search(r'(?<=boothNumber=")\d+', line)
                    if re.search(pattern, line):
                        sys.stdout.write(re.sub(pattern, match, line))

When I run this, my original.txt gets completely cleared of any text. I did a traceback and I get this:

in readconfig
for line in f1:
io.UnsupportedOperationo: not readable

UPDATE

I tried:

def readconfig(original_txt_path="original.txt", 
               new_txt_path="new.txt"):
    with open(new_txt_path) as f:
        for line in f:
            if not ('boothNumber=') in line:
                continue
            booth_number = int(line.replace('boothNumber=', ''))
            # do we need check if there are more than one 'boothNumber=...' line?
            break
    with open(original_txt_path) as f1:
        modified_lines = [line.startswith('boothNumber=') if not line
                          else 'boothNumber={}'.format(booth_number)  
                          for line in f1]
    with open(original_txt_path, mode='w') as f1:
        f1.writelines(modified_lines)

And I get error:

booth_number = int(line.replace('boothNumber=', ''))
ValueError: invalid literal for int() with base 10: '
(workstationID="1" "1" window=1= area="" extra parts of the line here)\n

the "1" after workstationID="1" is where the boothNumber=" " would normally go. When I open up original.txt, I see that it actually did not change anything.

UPDATE 3

Here is my code in full. Note, the file names are changed but I'm still trying to do the same thing. This is another idea or revision I had that is still not working:

import os
import shutil
import fileinput
import re  # used to replace string
import sys # prevents extra lines being inputed in config
           # example: sys.stdout.write


def convertconfig(pattern):                        
    source = "template.config"
    with fileinput.FileInput(source, inplace=True, backup='.bak') as file:
        for line in file:
            match = r'(?<=boothNumber=")\d+'
            sys.stdout.write(re.sub(match, pattern, line))


def readconfig():
    source = "bingo.config"
    pattern = r'(?<=boothNumber=")\d+'  # !!!!!!!!!! This probably needs fixed
    with fileinput.FileInput(source, inplace=True, backup='.bak') as file:
        for line in file:
            if re.search(pattern, line):
                fileinput.close()
                convertconfig(pattern)

def copyfrom(servername):

    source = r'//' + servername + '/c$/remotedirectory'
    dest = r"C:/myprogram"
    file = "bingo.config"
    try:
        shutil.copyfile(os.path.join(source, file), os.path.join(dest, file))

    except:
        print ("Error")

    readconfig()


# begin here
os.system('cls' if os.name == 'nt' else 'clear')
array = []
with open("serverlist.txt", "r") as f:
    for servername in f:

        copyfrom(servername.strip())

bingo.config is my new file template.config is my original

It's replacing the number in template.config with the literal string "r'(?<=boothNumber=")\d+'"

So template.config ends up looking like

boothNumber="r'(?<=boothNumber=")\d+'"

instead of

boothNumber="2"

Upvotes: 0

Views: 100

Answers (1)

Azat Ibrakov
Azat Ibrakov

Reputation: 11009

To find boothNumber value we can use next regular expression (checked with regex101)

(?<=\sboothNumber=\")(\d+)(?=\")

Something like this should work

import re
import sys # some of these are use for other code in my program

BOOTH_NUMBER_RE = re.compile('(?<=\sboothNumber=\")(\d+)(?=\")')
search_booth_number = BOOTH_NUMBER_RE.search
replace_booth_number = BOOTH_NUMBER_RE.sub


def readconfig(original_txt_path="original.txt", 
               new_txt_path="new.txt"):
    with open(new_txt_path) as f:
        for line in f:
            search_res = search_booth_number(line)
            if search_res is None:
                continue
            booth_number = int(search_res.group(0))
            # do we need check if there are more than one 'boothNumber=...' line?
            break
        else:
            # no 'boothNumber=...' line was found, so next lines will fail,
            # maybe we should raise exception like
            # raise Exception('no line starting with "boothNumber" was found')
            # or assign some default value
            # booth_number = -1
            # or just return?
            return

    with open(original_txt_path) as f:
        modified_lines = []
        for line in f:
            search_res = search_booth_number(line)
            if search_res is not None:
                line = replace_booth_number(str(booth_number), line)
            modified_lines.append(line)
    with open(original_txt_path, mode='w') as f:
        f.writelines(modified_lines)

Test

# Preparation
with open('new.txt', mode='w') as f:
    f.write('some\n')
    f.write('<jack Fill workstationID="1" boothNumber="56565" window="17" Code="" area="" section="" location="" touchScreen="False" secureWorkstation="false">')

with open('original.txt', mode='w') as f:
    f.write('other\n')
    f.write('<jack Fill workstationID="1" boothNumber="23" window="17" Code="" area="" section="" location="" touchScreen="False" secureWorkstation="false">')

# Invocation
readconfig()

# Checking output
with open('original.txt') as f:
    for line in f:
        # stripping newline character
        print(line.rstrip('\n'))

gives

other
<jack Fill workstationID="1" boothNumber="56565" window="17" Code="" area="" section="" location="" touchScreen="False" secureWorkstation="false">

Upvotes: 2

Related Questions