0

Is it possible to just replace a specific text's value in a file python? The below code replaces the string however I could'nt find a way to replace only the project_id or project_name's value.

import re 

def replace():
    with open("/Users/test/file.txt", "r") as sources:
        lines = sources.readlines()
    with open("/Users/test/file.txt", "w") as sources:
        for line in lines:
            sources.write(re.sub(r"Settings", 'Project_settings', line))

    
replace()

file.txt

Settings
######################
project_id = "468324678997"
project_name = "test"

output:

Project_settings
######################
project_id = "468324678997"
project_name = "test"

I would like to replace project_name's value to "abc"

Desired output: file.txt

Settings
######################
project_id = "468324678997"
project_name = "abc"
8
  • Can you add your desired output? Do you want to replace the word "test" in your example file? Commented Aug 6, 2021 at 3:52
  • What happened when you tried running the code, and how is that different from your desired result? Commented Aug 6, 2021 at 4:00
  • In your own words, where you have re.sub(r'^# project_name', 'abc', line), what exactly do you think that means? What source are you using to learn how to use regular expressions, and what happened when you tried following a tutorial? Commented Aug 6, 2021 at 4:01
  • Updated the question, i'm using re.sub to replace the string and it works. however i'm having issues to replace only the variable value using regex. Commented Aug 6, 2021 at 4:26
  • 1
    Why does your expected output have Settings and your code has Project_settings? Commented Aug 6, 2021 at 4:38

2 Answers 2

2

I suggest using a dictionary of config overrides, not regex

This way, you are not accidentally replacing all matching text

def replace(file, overrides):
    with open(file, "r") as sources:
        lines = sources.readlines()
    with open(file, "w") as sources:
        # skip the header rows
        next(lines)
        next(lines)
        for line in lines:
            config_key = line.split(' = ')[0]
            if config_key in overrides:
                sources.write('{} = {}\n'.format(config_key, overrides[config_key]))

overrides = {
  'project_name': 'abc'
}
replace("/Users/test/file.txt", overrides)

There are likely better Python libraries that can read property files and allow you to override specific values

Sign up to request clarification or add additional context in comments.

2 Comments

IMO, that isnt really needed because if the headers are removed you can just import config.py
So, we agree in that point: once recognized the major pattern of given file-format (and ignoring headers) you can just use existing libs to parse & modify.
1

Automate the text-editor's regex-replace

My recipe for replacing each matching line in an arbitrary formatted text-file.

As arguments to re.sub you could use a pair of regular-expressions: pattern-to-match and replacement, like regex-tuple (r'^Settings', r'Project_settings').

The data structure to store these could be a list of tuples (pairs), like replacements.

import re

replacements = [
    ('^Settings', 'Project_settings'),
    (r'^project_name = "(.*)"', r'project_name = "abc"'), # simply replaces with fixed value
    (r'^project_id = "(.*)"', r'project_id = "P-\1"')  # copies in the found group 1 at \1
]


def replace():
    lines = []
    with open("project_properties.cfg", "r") as config:
        for line in config.readlines():
            for pair in replacements:  # apply each replacement that matches line
                line = re.sub(pair[0], pair[1], line)  # substitute found pattern with replacement
            lines.append(line)  # add each read line to the buffer (if changed or not)

    with open("project_properties_.cfg", "w") as config: # Note: used a new filename
        config.writelines(lines)


replace()

Will result in desired output (plus inserting-replacement at project_id):

Project_settings
######################
project_id = "P-468324678997"
project_name = "abc"

Parsing and Updating with existing libs

As OneCricketeer's answer suggests:

When you manage to ignore the header, you will recognize strong similarity (i.e. key = value representation) to at least two common config-file formats:

This would allow you to research and find existing libraries, like Python's built-in configparser:

Comments

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.