Question

I would like to find text in file with regular expression and after replace it to another name. I have to read file line by line at first because in other way re.match(...) can`t find text.

My test file where I would like to make modyfications is (no all, I removed some code):

//...
#include <boost/test/included/unit_test.hpp>
#ifndef FUNCTIONS_TESTSUITE_H
#define FUNCTIONS_TESTSUITE_H
//...
BOOST_AUTO_TEST_SUITE(FunctionsTS)
BOOST_AUTO_TEST_CASE(test)
{
  std::string l_dbConfigDataFileName = "../../Config/configDB.cfg";
  DB::FUNCTIONS::DBConfigData l_dbConfigData;
//...
}
BOOST_AUTO_TEST_SUITE_END()
//...

Now python code which replace the configDB name to another. I have to find configDB.cfg name by regular expression because all the time the name is changing. Only the name, extension not needed.

Code:

import fileinput
import re

myfile = "Tset.cpp"

#first search expression - ok. working good find and print configDB
with open(myfile) as f:
  for line in f:
    matchObj = re.match( r'(.*)../Config/(.*).cfg(.*)', line, re.M|re.I)
    if matchObj:
      print "Search : ", matchObj.group(2)

#now replace searched expression to another name - so one more time find and replace - another way - not working - file after run this code is empty?!!!
for line in fileinput.FileInput(myfile, inplace=1):    
    matchObj = re.match( r'(.*)../Config/(.*).cfg(.*)', line, re.M|re.I)
    if matchObj:
      line = line.replace("Config","AnotherConfig")
Was it helpful?

Solution

From docs:

Optional in-place filtering: if the keyword argument inplace=1 is passed to fileinput.input() or to the FileInput constructor, the file is moved to a backup file and standard output is directed to the input file (if a file of the same name as the backup file already exists, it will be replaced silently).

What you need to do is just print line in every step of the loop. Also, you need to print line without additional newline, so you can use sys.stdout.write from sys module. As a result:

import fileinput
import re
import sys

...
for line in fileinput.FileInput(myfile, inplace=1):    
    matchObj = re.match( r'(.*)../Config/(.*).cfg(.*)', line, re.M|re.I)
    if matchObj:
      line = line.replace("Config","AnotherConfig")
    sys.stdout.write(line)

ADDED: Also I assume that you need to replace config.cfg to AnotherConfig.cfg. In this case, you can do something like this:

import fileinput
import re
import sys

myfile = "Tset.cpp"

regx = re.compile(r'(.*?\.\./Config/)(.*?)(\.cfg.*?)')

for line in fileinput.FileInput(myfile, inplace=1):    
    matchObj = regx.match(line, re.M|re.I)
    if matchObj:
        sys.stdout.write(regx.sub(r'\1AnotherConfig\3', line))
    else:
        sys.stdout.write(line)

You can read about function sub here: python docs.

OTHER TIPS

If I'm understanding you, you want to change in the line:

std::string l_dbConfigDataFileName = "../../Config/configDB.cfg";

just the file name 'configBD' to some other file name and rewrite the file.

First, I would suggest writing to a new file and changing the file names in case something goes wrong. Rather than use re.match use re.sub if there is a match it will return the line altered if not it will return the line unaltered -- just write it to a new file. Then change the filenames -- the old file to .bck and the new file to the old file name.

import re
import os

regex = re.compile(r'(../config/)(config.*)(.cfg)', re.IGNORECASE)

oldF = 'find_config.cfg'
nwF = 'n_find_config.cfg'
bckF = 'find_confg.cfg.bck'

with open ( oldF, 'r' ) as f, open ( nwF, 'w' ) as nf :
    lns = f.readlines()
    for ln in lns:
        nln = re.sub(regex, r'\1new_config\3', ln )
        nf.write  ( nln )


os.rename ( oldF, bckF )
os.rename ( nwF, oldF )
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top