562

I have a parameter file of the form:

parameter-name parameter-value

Where the parameters may be in any order but there is only one parameter per line. I want to replace one parameter's parameter-value with a new value.

I am using a line replace function posted previously to replace the line which uses Python's string.replace(pattern, sub). The regular expression that I'm using works for instance in vim but doesn't appear to work in string.replace().

Here is the regular expression that I'm using:

line.replace("^.*interfaceOpDataFile.*$/i", "interfaceOpDataFile %s" % (fileIn))

Where "interfaceOpDataFile" is the parameter name that I'm replacing (/i for case-insensitive) and the new parameter value is the contents of the fileIn variable.

Is there a way to get Python to recognize this regular expression or else is there another way to accomplish this task?

0

4 Answers 4

750

str.replace() v2|v3 does not recognize regular expressions.

To perform a substitution using a regular expression, use re.sub() v2|v3.

For example:

import re

line = re.sub(
           r"(?i)^.*interfaceOpDataFile.*$", 
           "interfaceOpDataFile %s" % fileIn, 
           line
       )

In a loop, it would be better to compile the regular expression first:

import re

regex = re.compile(r"^.*interfaceOpDataFile.*$", re.IGNORECASE)
for line in some_file:
    line = regex.sub("interfaceOpDataFile %s" % fileIn, line)
    # do something with the updated line
Sign up to request clarification or add additional context in comments.

3 Comments

I had to pass in flags=re.MULTILINE as the last argument to re.sub in order to get this to work, which makes sense - read about it in the docs here
regex compilations are cached (docs), so compiling isn't even necessary. But as you show, if one compiles, compile outside the loop.
For anyone that wants to know the details of whether or not to compile, check this answer.
529

You are looking for the re.sub function.

import re
s = "Example String"
replaced = re.sub('[ES]', 'a', s)
print(replaced)

will print axample atring

6 Comments

Is it possible to replace with case in one line, like if first character is E change to G, if Z change it to B for example.
You can pass a string -> string function as the second argument of re.sub. That function will be called with each matched substring, and its result will be put in the result.
if we want case insensitive substitution, we can put replaced = re.sub('[ES]', 'a', s, flags=re.IGNORECASE)
When use r before the search expression?
@Timo Regex often contains backslashes, which should not be escaped "by Python". stackoverflow.com/a/2081708/6371758
|
20

As a summary

import sys
import re

f = sys.argv[1]
find = sys.argv[2]
replace = sys.argv[3]
with open (f, "r") as myfile:
     s=myfile.read()
ret = re.sub(find,replace, s)   # <<< This is where the magic happens
print ret

Comments

11

re.sub is definitely what you are looking for. And so you know, you don't need the anchors and the wildcards.

re.sub(r"(?i)interfaceOpDataFile", "interfaceOpDataFile %s" % filein, line)

will do the same thing--matching the first substring that looks like "interfaceOpDataFile" and replacing it.

2 Comments

I need to replace the entire line because the original file will have something like: interfaceOpDataFile SomeDummyFile.txt and I will want to replace it with: interfaceOpDataFile SomeUsefulFile.txt If I don't include the anchors how will replace know that I want to get rid of SomeDummyFile.txt?
Ah, I mis-understood exactly what you were doing with the replacement. If each pair is on its own line, you still don't need the anchors explicity. re.sub(r"(?i)(interfaceOpDataFile).*", r'\1 UsefulFile', line) This will take the whole line, capture the arguement name, and add it back the the substitution for you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.