I have a file like divided in sections like that:
[main]
a
b
< sectionA
c
[sectionA]
x
< sectionB
y
z
[sectionB]
q
w
e
I want to replace the "< sectionA" w开发者_运维技巧ith contents from sectionA and so on. The final result should be a list with only the elements in the right order, like that: ['a', 'b', 'x', 'q', 'w', 'e', 'y', 'z', 'c']
A made the code below that fill the file in a dictionary with lists, but the order is not that I used in insertion (so I can't be sure where I start).
I also don't know the best way to replace the "< sectionA" things with the contents from the actual list...
import re
filename = input('Insert filename: ')
f = open(filename)
lines = f.readlines()
elements = {}
name = ''
for i in lines:
if i[-1] == '\n':
i = i[:-1]
if not i:
continue
sec = re.findall(r'\[(\w+)\]', i)
if sec != []:
name = sec[0]
elements[name] = []
else:
elements[name] += [i]
print(elements)
and the result is: {'main': ['a', 'b', '< sectionA', 'c'], 'sectionB': ['q', 'w', 'e'], 'sectionA': ['x', '< sectionB', 'y', 'z']}
I made some crazy code for you:
import collections
def load(fname):
d = collections.OrderedDict()
for i in (line.rstrip('\n') for line in open(fname) if line[:-1]):
d.update({i[1:-1]:[], '_':i[1:-1]}) \
if i.startswith('[') else d[d['_']].append(i)
return d
def join(first, dic):
f = dic[first]
for i,j in ((i,j[2:]) for i,j in enumerate(f) if j.startswith('<')):
f[i:i+1] = join(j, dic)
return f
d = load('file.txt')
join(next(iter(d)), d)
as the join
function inserts the code in the right list, it will not have to compute the lists more than once if required in two or more places. :)
Using OrderedDict, you always start with the right list.
It's not that hard. This is the algorithm:
1. Find all indexes in main starting with <.
2. If none are found, go to 5.
3. Replace every index with the according section (inserted unpacked).
4. Go to 1.
5. Done.
I solved your problem with two functions. The first for rendering the input file (renderfile(filename)
) into a Python dictionary, and the second to merge the contents with the section-references with a starting section (rendercontents(contents, startsection)
):
def renderfile(filename):
contents = {}
with open(filename) as f:
currentsection = ""
for line in f.readlines():
if line == "\n":
continue
line = line.replace("\n", "")
if line.startswith("["):
currentsection = line[1:-1]
contents[currentsection] = []
else:
contents[currentsection].append(line)
return contents
def rendercontents(contents, startsection):
returnlist = []
for line in contents[startsection]:
if line.startswith("<"):
returnlist.extend(rendercontents(contents, line[2:]))
else:
returnlist.append(line)
return returnlist
>>> newlist = rendercontents(renderfile("yourfile"), "main")
>>> newlist
['a', 'b', 'x', 'q', 'w', 'e', 'y', 'z', 'c']
精彩评论