我正在尝试从文本文件中获取数据。文本文件中的感兴趣的行是那些匹配“标记2”直到“标记3”的最后一个实例的行。可以有多个标记(重复)。我想要“标记2”的最小行号和“标记3”的最大行号 - 该最小/最大值内的所有文本。虽然这有效,但我希望看到如何以pythonic方式,更高效和更少的代码来实现这一点。
为什么我要两次打开同一个文件?它是否给了我,xreadlines和readlines相互冲突?
file_seeklines.py
import sys
filename = sys.argv[1]
line_number = []
number = 0
## Fetch the boundary(start, end points)
f = open(filename,'r')
for line in f.xreadlines():
number += 1
if "marker 2" in line.strip().lower():
line_number.append(number)
if "marker 3" in line.strip().lower():
line_number.append(number)
#print line_number[0], line_number[-1]
start, end = line_number[0]-1, line_number[-1]
f.close()
## Grab the boundary
g = open(filename,'r')
linelist = g.readlines()
try:
for i in xrange(start, end):
print linelist[i]
except:
print "failed"
pass
g.close()
file.txt的
Welcome notice
------------------------
Hello there, welcome! Foo
Marker 0
hello
world
Bar
Yes!
Foo
How are ya?!
Bar
Have a great day!
Marker 1
Hello 1 2
12
MarKer 2
Hello 23
23
Marker 3
Hello 34
34
marker 2
Hello 45
45
MArker 3
输出
MarKer 2
Hello 23
23
Marker 3
Hello 34
34
marker 2
Hello 45
45
MArker 3
答案 0 :(得分:4)
你是不是只使用正则表达式?即(marker 2.*marker 3)
re.DOTALL
和re.IGNORECASE
标志。
答案 1 :(得分:4)
如果你的文件不能大到read()
内存,你可以采用正则表达式方法(利用*
运算符贪婪的事实):
import re
with open(filename, 'r') as f:
inBetween = re.search(r"Marker 2(.*)Marker 3", f.read(), re.S | re.I).group()
另一种选择是在两个方向上迭代线,分别在第一次出现“Marker 2”和Marker 3“时停止:
with open(filename, 'r') as f:
lines = f.readlines
for i in range(len(lines)):
if "marker 2" in lines[i].lower():
start = i
break
else:
start = None
for i in range(len(lines), -1, -1):
if "marker 3" in lines[i].lower():
end = i
break
else:
end = None
if None not in (start, end):
inBetween = lines[start + 1:end]
else:
#one of the markers is missing, handle here.
答案 2 :(得分:2)
不要使用readlines()
,而是使用read()
,这样您就不必迭代线。
然后,您可以使用split()
找到您感兴趣的部分。
E.g。
with open(filename,'r') as f:
text = f.read().lower().split("marker 2",1)[1]
text = text.rsplit("marker 3",1)[0]
print('marker 2\n'+text+'marker 3')