【问题标题】:Changing a string by finding a specific string and replacing a following string通过查找特定字符串并替换后面的字符串来更改字符串
【发布时间】:2018-11-05 23:39:39
【问题描述】:

假设我在一个列表中有以下字符串集合:

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

现在我想找到字符串“item”并将下面的数字 5 替换为 f.e. 10 制作整条线:

item = 10

使用 regex 我找到“项目”没有问题,但不知道如何指向数字并更改它。

澄清:

最终目标是拥有一个在字符串列表中搜索给定字符串并交换与字符串关联的值的函数:

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

最好 change_value 可以是字符串或浮点数

【问题讨论】:

  • 我很困惑你说的是字符串集合并显示了定义的变量。那么具体是怎样的呢?
  • 更改为澄清

标签: python regex python-3.x


【解决方案1】:

您不仅需要找到item这个词,还可以在正则表达式中包含以下数字,并将整个内容替换为item = 10

\s+ 在正则表达式中匹配一个或多个空白字符,如果您希望空格是可选的,您可以使用\s*,它匹配零个或多个 空白字符。

>>> 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']

编辑

为了符合您的最新更改,即使其通用。让我们编写一个函数来搜索某个值并替换它的值。我将使用与目前相同的方法。

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

现在,让我们测试这个 change_parameter 方法的不同值:

>>> 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']

对于字符串和浮点数的替换:

>>> 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']

【讨论】:

  • 有没有办法让等号周围的空格字符成为有条件的?在我的数据中,可能有类似 -> "item=5" 的字符串,没有空格字符。
  • @Phil 我已编辑我的答案以符合您所需的更改。
  • 如何根据变量进行 re.compile?例如: this_match = olditem r= re.compile(r"this_match\s....)
  • @Phil 我已经更改了通用值替换的答案。
【解决方案2】:

一个更好、更通用的解决方案是使用re.sub 的记录能力来接受替换函数(给定一个匹配对象,您可以返回要替换的字符串)。您可以这样编写它,使其适用于任何key = val 字符串。当然有很多方法可以做到这一点,但你提到了正则表达式,所以这是一种方法......

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>.+)')

您可以根据需要调整正则表达式的确切语法。然后像这样使用它:

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

这将返回'item = 10'。无论 LHS 密钥是什么,这都将起作用。老实说,有更简单的方法可以做到这一点,但这个方法相当健壮。

【讨论】:

  • 如何更改“key”,以便 keyval_re 在另一个变量上发生变化?我只想找到特定字符串的匹配项。现在这段代码改变了匹配正则表达式的每一行
  • 那是一个简单得多的问题。只需在正则表达式中输入您要匹配的确切字符串即可。
  • 但我不能使用这个 f.e this_match = olditem r= re.compile(r"this_match\s....")。我也希望能够匹配不同的刺!
  • 对不起,我真的不确定你的意思。您刚刚写了“我真的只想找到特定字符串的匹配项”,然后您写了“我也希望能够匹配不同的字符串”。这是矛盾的。也许您应该更新您的问题以澄清或发布新问题。这可能有助于明确您要完成什么任务以及为什么要完成,因为现在它很模糊,我只能猜测最好的解决方案是什么,因为我真的不知道确切的问题是。
  • 改为澄清
【解决方案3】:

假设您要就地修改列表,以便我可以从其他答案中未探索的角度进行开发,我们可以继续使用列表元素的枚举,循环以便,对于所有以"item" 开头的列表元素,我们使用re.sub 来改变数字(而且只有数字……而且不仅是5,而是每个数字序列……)

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

附: 如果一个元素以item 开头并且不包含数字,则该元素将通过替换保持不变。

【讨论】:

    【解决方案4】:

    我不确定你所说的字符串集合是什么意思(在你的例子中,有定义的变量。但也许这适用于你的情况)使用 replace() 函数:

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

    返回所有出现的子字符串 old 的字符串 s 的副本 换成新的。如果给出了可选参数 maxreplace,则 第一次出现的 maxreplace 被替换。

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

    输出:

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

    【讨论】:

    • 替换对空格字符敏感吗?
    • @Phil 是的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多