我想获取所有匹配的数字(仅数字示例“ 0012--22”)或包含与之对应的文本(例如“ RF332”)的数字,这些文本与所提供的字符串列表相匹配(“ my_list”代码)。带数字的文本的显示格式就像是由一两个空格隔开。提供样本输入文件以供参考。
这是输入文件:
$cat input_file
some text before Expedien: 1-21-212-16-26 some random text
Reference RE9833 of all sentences.
abc
123
456
something blah blah Ref.:
tramite 1234567
Ref.:
some junk Expedien N° 18-00777 # some new content
some text Expedien N°18-0022995 # some garbled content
到目前为止,该脚本的附件如下:当前仅标识一个元素为{'tramite':'1234567'}
import re
import glob
import os
my_list = ['Ref.:', 'Reference', 'tramite', 'Expediente', 'Expediente No', 'Expedien N°', 'Exp.No', 'Expedien']
#open the file as input
with open('garb.txt','r') as infile:
res = dict()
for line in infile:
elems = re.split('(?::)?\s+', line)
#print(elems)
if len(elems) >= 2 :
contains = False
tmp = ''
for elem in elems:
if contains:
res.update({tmp : elem})
print(res)
contains = False
break
if elem in my_list:
contains = True
tmp = elem
#print(res)
这是预期的输出:
示例输出:
{'Expedien N°': '18-0022995'}
{'Expedien N°': '18-0022995'}
{'Expedien': '1-21-212-16-26'}
{'Reference' : 'RE9833'}
等等等
答案 0 :(得分:2)
您可以使用
(?<!\w)(your|escaped|keywords|here)\W*([A-Z]*\d+(?:-+[A-Z]*\d+)*)
请参见regex demo。
模式详细信息
(?<!\w)
-左侧单词边界(明确,\b
的含义取决于上下文,如果下一个字符是非单词char,则它将在左侧要求一个单词char,而并非是用户通常期望的东西)(your|escaped|keywords|here)
-捕获第1组:您的关键字列表,可以使用'|'.join(map(re.escape,my_list))
轻松构建(注意re.escape
是转义.
之类的特殊正则表达式元字符所必需的, +
,(
,[
等)\W*
-0+个非单词字符(字母,数字或_
以外的字符)([A-Z]*\d+(?:-+[A-Z]*\d+)*)
-捕获组2:
[A-Z]*
-零个或多个大写ASCII字母\d+
-1个或更多数字(?:-+[A-Z]*\d+)*
-重复0次或更多次
-+
-一个或多个连字符[A-Z]*\d+
-零个或多个大写ASCII字母,一个或多个数字请参见Python demo:
import re
s="""your_text_here"""
my_list = ['Ref.:', 'Reference', 'tramite', 'Expediente', 'Expediente No', 'Expedien N°', 'Exp.No', 'Expedien']
rx = r'(?<!\w)({})\W*([A-Z]*\d+(?:-+[A-Z]*\d+)*)'.format('|'.join(map(re.escape,my_list)))
print(re.findall(rx, s))
输出:
[('Expedien', '1-21-212-16-26'), ('Reference', 'RE9833'), ('tramite', '1234567'), ('Expedien N°', '18-00777'), ('Expedien N°', '18-0022995')]
答案 1 :(得分:1)
确实有必要允许少于50个代表点的用户发表评论,因为该线程是我非常好奇并希望分叉但又不想拥有的线程给出完整的答案,因为我给出的答案涉及有限的情况,而且不灵活。
@Wiktor Stribiewew
您的解决方案缺少“参考”。根据您的演示输出的一部分。看来他想跳过“ tramite”
@checkmate
在所需的输出中,您需要对其进行编辑,因为“ UV1234”不会显示在您发布的字符串中的任何地方
。
无论如何,我找到了解决方案,但我确实希望有人可以对此进行改进。
>>> import re
>>> string = '''some text before Expedien: 1-21-212-16-26 some random text
Reference RE9833 of all sentences.
abc
123
456
something blah blah Ref.:
tramite 1234567
Ref.:
some junk Expedien N° 18-00777 # some new content
some text Expedien N°18-0022995 # some garbled content'''
>>> re.findall('(?:(Expedien[\s]+N\S|Ref\.(?!:[\S\s]{,11}Expedien)|Reference|Expedien))[\S\s]*?([A-Z\-]*(?:[\d]+)[\S]*)', string)
[('Expedien', '1-21-212-16-26'), ('Reference', 'RE9833'), ('Ref.', '1234567'), ('Expedien N\xb0', '18-00777'), ('Expedien N\xb0', '18-0022995')]
缺陷: