我有一个以下格式的文本文件:
*CMD1,I1=0,I2=0,I3=0
*CMD2,I1=0,I2=1,I3=2
1,2,3
4,5,6
*CMD3,U1=0,U2=9,U3=8
4,5,6
3,4,6
*CMD3,U4=0
par,1,2
par,3,4
我想制作一个键值对。键是以*开头的行,值是下面的列表(所有内容,无论类型等等)。
我正在使用正则表达式来完成此任务。
我相信捕获以*开头的行的表达式是:
r'^ *\*.*'
这是我的代码:
import re, mmap, os
with open(fn,'r') as fin:
size = os.stat(fn).st_size
data = mmap.mmap(fin.fileno(), size, access=mmap.ACCESS_READ)
for m in re.finditer(r'^( *\*.*)(...)',data,re.M)
print 1
print m.group(1)
print 2
print m.group(2)
输出的(...)占位符应该是什么:
1
*CMD1,I1=0,I2=0,I3=0
2
1
*CMD2,I1=0,I2=1,I3=2
2
1,2,3
4,5,6
1
*CMD3,U1=0,U2=9,U3=8
2
4,5,6
3,4,6
1
*CMD3,U4=0
2
par,1,2
par,3,4
答案 0 :(得分:0)
以下是有效的正则表达式:(\*[\w,=]*)([\s\w,]*)
<强>说明:强>
此正则表达式有两个组:第一个(\*[\w,=]*)
用于键,仅匹配以“*”开头的任何行,而第二个([\s\w,]*)
匹配所有不以“*”开头的行。请注意,您必须删除值以删除不需要的空格。
<强>输出:强>
Match 1
1. *CMD1,I1=0,I2=0,I3=0
2.
Match 2
1. *CMD2,I1=0,I2=1,I3=2
2. 1,2,3 4,5,6
Match 3
1. *CMD3,U1=0,U2=9,U3=8
2. 4,5,6 3,4,6
Match 4
1. *CMD3,U4=0
2. par,1,2 par,3,4
答案 1 :(得分:0)
我想制作一个键值对。
我不认为正则表达式是实现目标的最佳方式。遍历这些行,将集合中的键设置为以'*'
开头的行,并将不以'*'
开头的行附加到值。
current_key = None
data_map = {}
for line in data.split('\n'):
if line.startswith('*'):
current_key = line
data_map[current_key] = []
else:
if current_key is None:
continue #no known key above, skip
data_map[current_key].append(line)
然后获取您的打印输出:
>>>for k, v in data_map.items():
print(1)
print(k)
print(2)
print(*v, '\n', sep = '\n')
1
*CMD3,U4=0
2
par,1,2
par,3,4
1
*CMD3,U1=0,U2=9,U3=8
2
4,5,6
3,4,6
1
*CMD1,I1=0,I2=0,I3=0
2
1
*CMD2,I1=0,I2=1,I3=2
2
1,2,3
4,5,6
答案 2 :(得分:0)
请原谅我这么直率但不需要正则表达式。你可以更简单地做到这一点。检查&#39; *&#39;的外观。一行开头的字符,并据此采取行动。
>>> begun = False
>>> with open('temp.txt') as text:
... for line in text.readlines():
... if not line:
... break
... line = line.strip()
... if line.startswith('*'):
... if begun:
... print ()
... else:
... begun = True
... print (1)
... print (line)
... print (2)
... else:
... print (line)
...
1
*CMD1,I1=0,I2=0,I3=0
2
1
*CMD2,I1=0,I2=1,I3=2
2
1,2,3
4,5,6
1
*CMD3,U1=0,U2=9,U3=8
2
4,5,6
3,4,6
1
*CMD3,U4=0
2
par,1,2
par,3,4
答案 3 :(得分:0)
正如其他人发布的那样,str.startwith('*')
足以检测一行是否以'*'开头。作为Raymond Hettinger在itertools
和groupby
中工作的粉丝,我提供了这种迭代几个群体的方法:
from itertools import groupby
def generate_groups(text):
key_fn = lambda s: s.startswith('*')
last = None
for leading_star, following in groupby(text.splitlines(), key=key_fn):
if not leading_star:
# multiple rows not starting with '*', these are subs of last '*' row
yield (last, list(following))
last = None
else:
# multiple rows starting with '*'
for f in following:
if last is not None:
yield (last, [])
last = f
if last is not None:
yield (last, [])
print(sample)
for group in (generate_groups(sample)):
print(group)
打印
*CMD1,I1=0,I2=0,I3=0
*CMD2,I1=0,I2=1,I3=2
1,2,3
4,5,6
*CMD3,U1=0,U2=9,U3=8
4,5,6
3,4,6
*CMD3,U4=0
par,1,2
par,3,4
('*CMD1,I1=0,I2=0,I3=0', [])
('*CMD2,I1=0,I2=1,I3=2', ['1,2,3', '4,5,6'])
('*CMD3,U1=0,U2=9,U3=8', ['4,5,6', '3,4,6'])
('*CMD3,U4=0', ['par,1,2', 'par,3,4'])
答案 4 :(得分:-1)
我尝试for m in re.finditer(r'^( *\*.*)([^*]+)',data,re.M):
并且它似乎提供了有效的结果,使用strip()
修剪任何空格并且可以找到确切的输出,
1
* CMD1,I1 = 0,I2 = 0,I3 = 0
2
1 * CMD2,I1 = 0,I2 = 1,I3 = 2
2
1,2,3
4,5,6
1
* CMD3,U1 = 0,U2 = 9,U3 = 8
2
4,5,6
-3,4,6-
1
* CMD3,U4 = 0
2
参数,1,2-
参数,3,4-