10
votes

I'm trying to get re.sub to replace a pattern specified with a value for example

for lines in f:
    pattern='\${2}'+key[0]+'\${2}'
    re.search(pattern,lines)

this return the line where the pattern was found. For example this is one of the test returns if got

this is a $$test$$

The problem i'm having is when i do the following

re.sub(pattern,key[1],lines)

nothing happens. What am i missing? For more info key[0]=test and key[1]=replace so what i'm trying to do is whenever "$$test$$" is encountered it will replace it with "replace". I have no problem finding "$$test$$" but for some reason re.sub isn't replacing it.

2
When you need to store a backslash in a string it's better to use the double backslash form. In your case it works anyway in Python because the dollar sign has no special meaning when prefixed with a backslash and because Python in that case maintains both chars, but in other languages writing '\$' is going to mean just '$'. When someone is reading a string and finds a backslash expects something special or another backslash. If you need many backslashes in a string then you should use use a raw string... - 6502
For people landing here with general re.sub problems, make sure you are passing re.IGNORECASE as a flags= argument, not the count argument. - Noumenon

2 Answers

17
votes

You are assigning the result of re.sub back to a variable, right? e.g.

lines = re.sub(pattern, key[1], lines)

It's a string, so it can't be changed (strings are immutable in Python), therefore a new string is created and returned to you. If you don't assign it back to a name, you will lose it.

1
votes

If you have a text, you can run re.sub() directly on the whole text as follows:

import re

ss = '''that's a line
another line
a line to $$test$$
123456
here $$test$$ again
closing line'''

print(ss,'\n')

key = {0:'test', 1:'replace'}

regx = re.compile('\$\${[0]}\$\$'.format(key))

print( regx.sub(key[1],ss) )

.

If you read a file, you should have interest to read the whole file and put it in an object ss before runing re.sub() on it, instead of reading and replacing line after line

.

And if you have a list of lines , you must process as follows:

import re

key = {0:'test', 1:'replace'}

regx = re.compile('\$\${[0]}\$\$'.format(key))

lines = ["that's a line",
         'another line',
         'a line to $$test$$',
         '123456',
         'here $$test$$ again',
         'closing line']

for i,line in enumerate(lines):
    lines[i] =  regx.sub(key[1],line)

Otherwise a line containing '$$test$$' wouldn't be modified:

import re

key = {0:'test', 1:'replace'}

regx = re.compile('\$\${[0]}\$\$'.format(key))

lines = ["that's a line",
         'another line',
         'a line to $$test$$',
         '123456',
         'here $$test$$ again',
         'closing line']

for line in lines:
    line =  regx.sub(key[1],line)


print (lines)

result

["that's a line", 'another line', 'a line to $$test$$', '123456', 'here $$test$$ again', 'closing line']