0

Let's say I have the following collection of strings inside a list:

list_of_strings = [     
     "data_1 = 3,",
     "re = 3,",
     "item = 5"]

Now I want to find the string "item" and replace the following number 5 with f.e. 10 making the whole line:

item = 10

using regex I have no problem finding "item", but have no idea how I can point to the number and change it.

Clarification:

The ultimate goal is to have a function that searches for a given string inside a list of strings and exchange the value associated with the string:

match_str = item_x
change_value = 10
list = ["string1","string2","string5","item_x = 3", ...]
change_parameter(match_str,change_value,list)  

Preferably change_value can be a string or a float

2
  • 7
    I'm confused you're saying collection of strings and showed defined variables. So how it's exactly? Commented Nov 4, 2018 at 12:42
  • changed it to clarify Commented Nov 4, 2018 at 12:53

4 Answers 4

3

You don't just need to find the word item, you can also include the following number in the regex, and replace the whole thing with item = 10.

\s+ in regex matches for one or more white-space characters, if you want spaces to be optional, you can use \s*, which matches for zero or more white-space characters.

>>> l = ['data_1 = 3', 're = 3', 'item = 5']

>>> import re
>>> r = re.compile(r'item\s*=\s*\d+')
>>> updated_l = [r.sub('item = 10', s) if r.match(s) else s for s in l]

>>> print(updated_l)
['data_1 = 3', 're = 3', 'item = 10']

Edit:

To comply your latest changes, i.e. to make it generic. Let's write up a function which searches for some value and replaces it's value. I'll be using the same approach which I currently have.

def change_parameter(match_str, change_value, list1):
    # First, let's create a regex for it, and compile it
    r = re.compile(r'{0}\s*=\s*\d+'.format(match_str))

    # Find, and replace the matching string's value
    updated_l = [r.sub('{0} = {1}'.format(match_str, change_value), s) if r.match(s) else s for s in list1]
    return updated_l

Now, let's test this change_parameter method for different values:

>>> l = ['data_1 = 3', 're = 3', 'item = 5']
>>> change_parameter('item', 10, l)
['data_1 = 3', 're = 3', 'item = 10']
>>> change_parameter('re', 7, l)
['data_1 = 3', 're = 7', 'item = 5']

And for string and float replacements:

>>> change_parameter('re', 7.1, l)
['data_1 = 3', 're = 7.1', 'item = 5']
>>> change_parameter('data_1', '11', l)
['data_1 = 11', 're = 3', 'item = 5']
Sign up to request clarification or add additional context in comments.

4 Comments

is there a way to have the space chars around the equal sign to be conditional? In my data it is possible to have string like -> "item=5" with no space chars.
@Phil I have edited my answer to comply with your required changes.
How can i make the re.compile depending to a variable? For example: this_match = olditem r= re.compile(r"this_match\s....) <- this obviously doesnt work
@Phil I have changed my answer for generic value replacement.
1

A better, more general solution to what you're trying to do is to use the documented ability of re.sub to accept a substitution function (given a Match object you can return the string to substitute). You can write this in such a way that it will work for any key = val string. There are many ways to do this of course but you mentioned regular expressions so this is one way...

from functools import partial
import re

def subst_val(newval, m):
    return '{} = {}'.format(m.group('key'), newval)

keyval_re = re.compile(r'(?P<key>[^= ]+)\s*=\s*(?P<val>.+)')

Where you might adjust the regex depending on the exact syntax for your needs. Then use it like:

keyval_re.sub(partial(subst_val, 10)), 'item = 5')

which will return 'item = 10'. This will work the same regardless what the LHS key is. Honestly there are simpler ways to do this but this one is reasonably robust.

5 Comments

how can I change "key" so that keyval_re is changing upon another variable? I only really want to find the match for a specific string. Right now this code changes every line that matches the regex
That's a much simpler question then. Just put the exact string you want to match in the regular expression.
But I cant use this f.e this_match = olditem r= re.compile(r"this_match\s...."). I want to be able to match different stings aswell!
Sorry, I'm really not sure what you mean. You just wrote "I really only want to find the match for a specific string" but then you wrote "I want to be able to match different strings as well". This comes off as contradictory. Perhaps you should update your question to clarify or post a new one. It might help to clarify exactly what task you're trying to accomplish and why, because right now it's vague and I can only guess what the best solution is since I don't really know what the exact problem is.
changed to clarify
0

Assuming that you want to modify your list in place, so that I can develop from an angle unexplored in other answers, we can proceed using an enumeration of the list elements, looping so that, for all the list elements that start with "item", we use re.sub to change the number (and only the number... and not only 5 but every digit sequence...)

for i, element in enumerate(data):
    if element.startswith("item"):
        data[i] = re.sub("[0-9]+", "10", element)

P.S. if an element starts with item and doesn't contain a number, the element is left unchanged by the substitution.

Comments

-1

I'm not sure what you mean by collection of strings (In your example there are defined variables. But maybe this will work in your case) Use replace() function:

string.replace(s, old, new[, maxreplace])

Return a copy of string s with all occurrences of substring old replaced by new. If the optional argument maxreplace is given, the first maxreplace occurrences are replaced.

string = """
    data_1 = 3,
    re = 3,
    item = 5.
"""
new_str = string.replace("item = 5", "item = 10")
print(new_str)

Output:

data_1 = 3,
re = 3,
item = 10.

2 Comments

is replace sensitive to space characters?
@Phil Yes it is

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.