Получить число, присутствующее после определенного шаблона соответствующей строки в Python - PullRequest
2 голосов
/ 08 марта 2019

Я хочу получить все совпадающие номера (например, только цифры '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'}

и т. Д. И т. Д.

Ответы [ 2 ]

2 голосов
/ 10 марта 2019

Вы можете использовать

(?<!\w)(your|escaped|keywords|here)\W*([A-Z]*\d+(?:-+[A-Z]*\d+)*)

См. Демоверсию regex .

Детали шаблона

  • (?<!\w) - граница левого слова (однозначно, значение \b зависит от контекста, и если следующий символ не является символом, не состоящим из слов, для него потребуется слово 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, 1 или более цифр

Смотрите Python демо :

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 голос
/ 08 марта 2019

На самом деле должно быть что-то, что позволяет пользователям с более чем 50 или более точками повторения комментировать, потому что эта тема - одна из тех, которые мне действительно интересны и которые я хочу раскошелиться, но не хотел иметьдать полноценный ответ, потому что ответ, который я даю, включает в себя конечные ситуации и не гибкий.

@ Wiktor Stribiżew

Ваше решениепропускает "Реф."часть вывода на основе вашей демонстрации.Похоже, он хочет пропустить "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')]

Недостатки:

  • Для правильного захвата он частично полагается на "Ссылка (?!: [\ S \ s] {, 11} Expedien)"
  • Во-первых, «11» необходимо отредактировать, чтобы учесть другие объемы информации, которая может присутствовать, поэтому она не является гибкой
  • Во-вторых, если вместо этого следует «Ссылка» какпротив тогдашнего третьего "Реф."будет захвачено неправильно
...