查找字符串并替换下一行为某事

2024-03-28 20:40:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个Python脚本,它将要求一个文件和一个名称(例如“John”)。你知道吗

该文件包含一大堆这样的行:

...
Name=John
Age=30
Pay=1000
Married=1
Name=Bob
Age=25
Pay=500
Married=0
Name=John
Age=56
Pay=3000
Married=1
...

我想打开这个文件,要求用户提供一个名称,并替换与该名称匹配的所有条目的pay值。因此,例如,用户输入“John”,我想将所有“John”的Pay更改为,比如说,5000。其他名字的支付值不变。你知道吗

到目前为止,我已经打开了文件,并将所有内容连接到一个长字符串中,以使事情变得更简单:

for line in file:
    file_string += line

一开始,我在考虑某种字符串替换,但没有成功,因为我会搜索“John”,但我不想替换“John”,而是要替换向下两行的Pay值。你知道吗

我开始用正则表达式来代替它,并想出了这样的方法。你知道吗

# non-greedy matching
re.findall("Name=(.*?)\nAge=(.*?)\nPay=(.*?)\n", file_string, re.S)

好吧,这就列出了一个三元组的列表,看起来一切都很好。现在,要做实际的替换。。。你知道吗

我在StackOverflow上读到另一个问题,我可以设置一个分组的名称并在以后使用该分组…:

re.sub(r'Name=(.*?)\nAge=(.*?)\nPay=', r'5000', file_string, re.S)

我试着看它是否能工作,并用5000替换所有的名字,但它没有,如果能,我可能会检查第一个组,看看它是否匹配用户输入的名字或什么。你知道吗

另一个问题是,我在Python文档中看到,re.sub只替换最左边的引用。我要替换所有事件。我该怎么做?你知道吗

现在我有点不知所措,如果有人能帮我的话,那就太好了!你知道吗


Tags: 文件字符串用户namere名称agestring
3条回答

我不认为正则表达式是解决这个问题的最佳方法。我喜欢更一般的解决方案。其他答案取决于以下一个或多个因素:

  1. 一个人总有4种属性。你知道吗
  2. 每个人都有相同的属性。你知道吗
  3. 属性的顺序总是相同的。你知道吗

如果这些在你的例子中是真的,那么regex就可以了。你知道吗

我的解决方案比较冗长,但并不依赖于这些。它处理混合/缺失属性、混合顺序,并能够设置和获取任何属性值。您甚至可以稍微扩展它,如果需要,还可以支持新的属性或人员插入。你知道吗

我的代码:

# i omitted "data = your string" here

def data_value(person_name, prop_name, new_value = None):
    global data
    start_person = data.find("Name=" + person_name + "\n")
    while start_person != -1:
        end_person = data.find("Name=", start_person + 1)
        start_value = data.find(prop_name + "=", start_person, end_person)        
        if start_value != -1:
            start_value += len(prop_name) + 1
            end_value = data.find("\n", start_value, end_person)
            if new_value == None:
                return data[start_value:end_value]
            else:
                data = data[:start_value] + str(new_value) + data[end_value:]                
        start_person = data.find("Name=" + person_name + "\n", end_person)
    return None

print data_value("Mark", "Pay")    # Output: None (missing person)
print data_value("Bob", "Weight")  # Output: None (missing property)
print data_value("Bob", "Pay")     # Output: "500" (current value)
data_value("Bob", "Pay", 1234)     # (change it)
print data_value("Bob", "Pay")     # Output: "1234" (new value)

data_value("John", "Pay", 555)     # (change it in both Johns)

以下代码将满足您的需要:

import re

text = """
Name=John
Age=30
Pay=1000
Married=1
Name=Bob
Age=25
Pay=500
Married=0
Name=John
Age=56
Pay=3000
Married=1
"""

# the name you're looking for
name = "John"
# the new payment
pay = 500

print re.sub(r'Name={0}\nAge=(.+?)\nPay=(.+?)\n'.format(re.escape(name)), r'Name=\1\nAge=\2\nPay={0}\n'.format(pay), text)

一次迭代4行。如果第一行包含“John”,请编辑后面两行的内容。你知道吗

data = """
Name=John
Age=30
Pay=1000
Married=1
Name=Bob
Age=25
Pay=500
Married=0
Name=John
Age=56
Pay=3000
Married=1
"""

lines = data.split() 
for i, value in enumerate(zip(*[iter(lines)]*4)):
    if 'John' in value[0]:
        lines[i*4 + 2] = "Pay=5000"

print '\n'.join(lines)

相关问题 更多 >