4

If I have a file contents like this:

old_string
-old_string

I want to change only "old_string" to be "+new_string" so the result looks like

+new_string
-old_string

my code gives this result:

+new_string
-+new_string

This is my code :

    with open(filename) as f:

    s = f.read()

    if old_string not in s:

        return False

with open(filename, 'w') as f:

    s = s.replace(old_string, new_string)

    f.write(s)

    return True

i Tried regex, but it won't work since I pass the regex as a variables, this is what I did so far:

    with open (filename, 'r' ) as f:

       content = f.read()

content_new = re.sub('(\%old_string)', r'\new_string'%(old_string,new_string), content, flags = re.M)      
2
  • You can probably write your own implementation of replace that checks if the previous char is a '-'. Commented Feb 18, 2017 at 15:07
  • @Adam - Would really appreciate it if you marked the answer that helped you solve your problem as the correct answer :-) Commented Feb 18, 2017 at 15:26

4 Answers 4

1

You could just ignore the lines which have a hyphen("-") at the beginning, and replace the rest.

The script below is a little different from yours. I have put in comments to help you understand. This should be easy to understand.

filename ="some_file"
output_filename = "some_other_file"

old_string = "old_string"
new_string = "+new_string"

input_file_handle = open(filename,"r") # File being opened in read mode
output_file_handle = open(output_filename, "w") # File being opened in write mode

# Read in input file line by line
for line in input_file_handle:

    # Write to output file and move on to next line
    if old_string not in line:
        output_file_handle.write(line+"\n")
        continue

    # This line contains the old_string. We check if it starts with "-". 
    # If it does, write original line and move on to next line
    if line.startswith("-"):
        output_file_handle.write(line+"\n")
        continue


    # At this stage we are absolutely sure we want to replace this line's contents
    # So we write the replaced version to the new file
    output_file_handle.write(new_string+"\n")


# Close both file handles
input_file_handle.close()
output_file_handle.close()
Sign up to request clarification or add additional context in comments.

Comments

1

The syntax is a bit off; you'll probably want to do something more like this:

import re

test_str = ("old_string\n"
            "-old_string")

match = "old_string"
subst = "+new_string"

regex = r"^{}".format(match)

# You can manually specify the number of replacements by changing
# the 4th argument

result = re.sub(regex, subst, test_str, 0)

if result:
    print (result)

# Note: for Python 2.7 compatibility, use ur"" to prefix 
# the regex and u"" to prefix the test string and substitution. 

The ^ assertion in the pattern is something I recommend using, as it indicates the string to match should start at the very beginning of the line thus won't match -old_string.

Comments

1

A benefit to my solution is that it does not rely on the "do-not-replace" prefix being at the beginning of the line.

If you wanted to solve this problem without regular expressions you could write your own replace method:

replace.txt:

old_string
-old_string

old_string -old_string --old_string old_string

replace.py:

import sys
import fileinput

def replace_exclude(string, search, replace="", excluding_char='-'):
    # Does replace unless instance in search string is prefixed with excluding_char.
    if (not string) or (not search): return None
    for i in range(len(string)):
        while string[i-1] == excluding_char:
            i += 1
        if i < len(string):
            for j in range(len(search)):
                possible = True
                if not (string[i + j] == search[j]):
                    possible = False
                    break
        if possible:
            string = string[0:i] + replace + string[i+len(search):]
            i += len(replace)
    return string

filename = "replace.txt"

for line in fileinput.input([filename], inplace=True):
    sys.stdout.write(replace_exclude(line, "old_string", "+new_string"))

replace.txt after running replace.py:

+new_string
-old_string

+new_string -old_string --old_string +new_string

4 Comments

Hey Greg, Would that work for python 2.7 ? I get error in print(replace_exclude(line, "old_string", "+new_string"), end='')
Oh, no I develop in Python 3, and I recommend you upgrade to it. If you want specific answers in the old, outdated, legacy Python 2, then you should tag your question specifically python2.x or python2.7.
As an aside, I should say that my claim that Python 2 is legacy should be backed by evidence: wiki.python.org/moin/Python2orPython3
I edited my answer to include Python 2.7 support by using sys.stdout.write instead of print. The actual replace_exclude method didn't need to change, just the method of writing out.
-1

This will work for you:-

import re
with open("output.txt", "a") as myfile:

    with open('input.txt') as f:
        lines = f.readlines()
        for line in lines:
            # print str(line)
            ret = re.sub(r"(\s|^|$)old_string(\s|^|$)",r" +new_string ",line) #It will replace if line contain 'old_string' by '+new_string'
            # print ret
            myfile.write(ret+'\n')

Note:- Check output.txt

7 Comments

where did you specify "old_string" ?
@Adam Input string is your old string.
@Adam,check I have update the ans try to run this by replacing your file name.
That seems to be fine, but if I have old_string after a word like for example options old_string. it returns it like options+new_string maybe I didn't explain it in my question
Yes I tried it, it works fine if the old_string in the start of the sentence, but if it comes after a string as I explained, it mess it up.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.