我正在编写一个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
...
我想打开此文件,询问用户名称,并替换与该名称匹配的所有条目的付款值。因此,例如,用户输入“John”,我想将所有“John”的Pay更改为5000,其他名称的Pay值不会改变。
到目前为止,我已打开文件并将所有内容连接成一个长字符串,以使事情变得更容易:
for line in file:
file_string += line
起初,我正在考虑某种字符串替换,但是由于我会搜索“John”但我不想取代“John”,而是替换“John”,而不是Pay值。两行下来。
我开始使用正则表达式,并想出了类似的东西。
# non-greedy matching
re.findall("Name=(.*?)\nAge=(.*?)\nPay=(.*?)\n", file_string, re.S)
好吧,这样就会吐出这些分组的3元组列表,它似乎确实找到了一切。现在,做实际的替换...
我在StackOverflow上的另一个问题上读到,我可以设置分组的名称并稍后使用该分组......:
re.sub(r'Name=(.*?)\nAge=(.*?)\nPay=', r'5000', file_string, re.S)
我试过看看它是否会起作用并将所有名称替换为5000,但事实并非如此。如果它那么我可能会检查第一组,看它是否与用户输入的名称相匹配。
另一个问题是我在Python文档中读到re.sub
仅替换最左边的事件。我想替换所有出现的事件。我该怎么做?
现在,如果有人能帮助我,我会有点失去这样做会很棒!
答案 0 :(得分:2)
一次迭代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)
答案 1 :(得分:2)
我不认为正则表达式是解决此问题的最佳方法。我更喜欢更通用的解决方案其他答案取决于以下一项或多项:
如果你的情况属实,那么正则表达式就可以了。
我的解决方案更详细,但并不依赖于这些。它处理混合/缺失属性,混合顺序,并能够设置和获取任何属性值。您甚至可以延长它,并在需要时支持新的财产或人员插入。
我的代码:
# 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)
答案 2 :(得分:1)
以下代码将满足您的需求:
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)