Python 将所有名称与末尾的5位数字完全匹配
我有这样一个文本文件:Python 将所有名称与末尾的5位数字完全匹配,python,regex,file,Python,Regex,File,我有这样一个文本文件: john123: 1 2 coconut_rum.zip bob234513253: 0 jackdaniels.zip nowater.zip 3 judy88009: dontdrink.zip 9 tommi54321: dontdrinkalso.zip 92 ... 我有数百万这样的作品 我想取一个5位数的名字和号码。我试过这个: matches = re.findall(r'\w*\d{5}:',filetext2) 但它给我的结果至少有5位数
john123:
1
2
coconut_rum.zip
bob234513253:
0
jackdaniels.zip
nowater.zip
3
judy88009:
dontdrink.zip
9
tommi54321:
dontdrinkalso.zip
92
...
我有数百万这样的作品
我想取一个5位数的名字和号码。我试过这个:
matches = re.findall(r'\w*\d{5}:',filetext2)
但它给我的结果至少有5位数
['bob234513253:', 'judy88009:', 'tommi54321:']
问题1:如何找到正好有5位数字的名称
问题2:我想用5位数字附加与这些名称相关联的zip文件。如何使用正则表达式执行此操作?这是因为\w包含数字字符:
>>> import re
>>> re.match('\w*', '12345')
<_sre.SRE_Match object at 0x021241E0>
>>> re.match('\w*', '12345').group()
'12345'
>>>
关于第二个问题,您可以使用以下内容:
import re
# Dictionary to hold the results
results = {}
# Break-up the file text to get the names and their associated data.
# filetext2.split('\n\n') breaks it up into individual data blocks (one per person).
# Mapping to str.splitlines breaks each data block into single lines.
for name, *data in map(str.splitlines, filetext2.split('\n\n')):
# See if the name matches our pattern.
if re.match('[A-Za-z]*\d{5}:', name):
# Add the name and the relevant data to the file.
# [:-1] gets rid of the colon on the end of the name.
# The list comprehension gets only the file names from the data.
results[name[:-1]] = [x for x in data if x.endswith('.zip')]
或者,在没有所有评论的情况下:
import re
results = {}
for name, *data in map(str.splitlines, filetext2.split('\n\n')):
if re.match('[A-Za-z]*\d{5}:', name):
results[name[:-1]] = [x for x in data if x.endswith('.zip')]
下面是一个演示:
>>> import re
>> filetext2 = '''\
... john123:
... 1
... 2
... coconut_rum.zip
...
... bob234513253:
... 0
... jackdaniels.zip
... nowater.zip
... 3
...
... judy88009:
... dontdrink.zip
... 9
...
... tommi54321:
... dontdrinkalso.zip
... 92
... '''
>>> results = {}
>>> for name, *data in map(str.splitlines, filetext2.split('\n\n')):
... if re.match('[A-Za-z]*\d{5}:', name):
... results[name[:-1]] = [x for x in data if x.endswith('.zip')]
...
>>> results
{'tommi54321': ['dontdrinkalso.zip'], 'judy88009': ['dontdrink.zip']}
>>>
请记住,一次读入文件的所有内容不是很有效。相反,您应该考虑生成生成器函数,以一次生成数据块。此外,您还可以通过预编译正则表达式模式来提高性能。您需要将正则表达式限制在单词末尾,以便它不会与使用\b 例如,见 正则表达式将匹配
judy88009:
tommi54321:
python代码如下
>>> re.findall(r'[a-zA-Z]+\d{5}\b', x)
['judy88009', 'tommi54321']
输出
议论
我试图保持它非常简单,如果您的输入很长,您应该按照iCodez的建议,实现一个生成器,一次生成一条记录,而对于regexp匹配,我尝试了一些优化,只搜索头的最后7个字符
附录:记录生成器的简化实现
您可能应该将括号从字符串的开头包装到冒号之前,这样冒号就不会包含在用户名字符串中。谢谢。我如何用这个regex和这个用户名下的zip文件列出一个列表?@new_coder-很抱歉耽搁了;突然出现了一些重要的事情。我编辑的帖子回答了你的第二个问题。嗨。还有一件事。如果我不想硬编码5号怎么办?类似这样的东西------------------->如果re.match'[A-Za-z]*\d{num}:',name:where num=5可以这样做吗?@new_coder-你可以用它插入你想要的任何数字:'[A-Za-z]*\d{{num}:'.formatnum=5产生'[A-Za-z]*\d{5}:'。请注意,您需要额外的大括号,因为{…}表示格式字段。
judy88009:
tommi54321:
>>> re.findall(r'[a-zA-Z]+\d{5}\b', x)
['judy88009', 'tommi54321']
import re
results = {}
with open('datazip') as f:
records = f.read().split('\n\n')
for record in records:
lines = record.split()
header = lines[0]
# note that you need a raw string
if re.match(r"[^\d]\d{5}:", header[-7:]):
# in general multiple hits are possible, so put them into a list
results[header] = [l for l in lines[1:] if l[-3:]=="zip"]
print results
{'tommi54321:': ['dontdrinkalso.zip'], 'judy88009:': ['dontdrink.zip']}
import re
def records(f):
record = []
for l in f:
l = l.strip()
if l:
record.append(l)
else:
yield record
record = []
yield record
results = {}
for record in records(open('datazip')):
head = record[0]
if re.match(r"[^\d]\d{5}:", head[-7:]):
results[head] = [ r for r in record[1:] if r[-3:]=="zip"]
print results