Python 正则表达式以匹配文件和分组中的节
我有一个以下格式的文本文件:Python 正则表达式以匹配文件和分组中的节,python,regex,parsing,Python,Regex,Parsing,我有一个以下格式的文本文件: *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 我想做一个键值对。键是以*开头的行,值是下面的列表(所有内容,无论类型等) 我使用regex就是为了完成这个任务 我认为用*开头的行来表示: r'^ *\*.*' 这是我的密码: import re, mmap, os with ope
*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
我想做一个键值对。键是以*开头的行,值是下面的列表(所有内容,无论类型等)
我使用regex就是为了完成这个任务
我认为用*开头的行来表示:
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
下面是有效的正则表达式:
(\*[\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
我在re.finditer(r'^(*\*.*)([^*]+)、data、re.m中尝试了
,它似乎给出了有效的结果,使用strip()
修剪任何空白,可以找到确切的输出
一,
*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
二,
标准杆,1,2
标准杆,3,4
我想做一个键值对
我不认为正则表达式是实现目标的最佳方式。遍历这些行,将集合中的键设置为以'*'
开头的行,并将不以'*'
开头的行附加到值中
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
请原谅我的直言不讳,但没有必要使用正则表达式。你可以做得更简单一些。检查行首是否出现“*”字符,并采取相应措施
>>> 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
正如其他人所发布的,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'])
@谢谢你的提示,billy,就我所知,我已经做了建议的更改,如果有不同/更好的方法,请分享我不确定,问对不对,因为尽管得到了正确的结果,但答案被标记为无效,我想知道我的解决方案是否错误,