Разбор регулярного выражения из файла YAML добавляет дополнительные \ - PullRequest
0 голосов
/ 06 мая 2020

У меня есть набор регулярных выражений, которые я использую для очистки множества определенных c полей из текстового документа. Все они отлично работают при использовании непосредственно внутри сценария python.

Но я думал поместить их в файл YAML и читать оттуда. Вот как это выглядит:

# Document file for Regular expression patterns for a company invoice

---

    issuer: ABCCorp
    fields:
      invoice_number: INVOICE\s*(\S+)
      invoice_date: INVOICE DATE\s*(\S+)
      cusotmer_id: CUSTOMER ID\s*(\S+)
      origin: ORIGIN\s*(.*)ETD
      destination: DESTINATION\s*(.*)ETA
      sub_total: SUBTOTAL\s*(\S+)
      add_gst: SUBTOTAL\s*(\S+)
      total_cost: TOTAL USD\s*(\S+)
      description_breakdown: (?s)(DESCRIPTION\s*GST IN USD\s*.+?TOTAL CHARGES)
      package_details_fields: (?s)(WEIGHT\s*VOLUME\s*.+?FLIGHT|ROAD REFERENCE)
      mawb_hawb: (?s)((FLIGHT|ROAD REFERENCE).*(MAWB|MASTER BILL)\s*.+?GOODS COLLECTED FROM)

Когда я извлекаю его с помощью pyyml в python, он добавляет вокруг него строковую цитату (что нормально, поскольку я могу добавить r '' позже), но я это вижу также добавляет дополнительный \ между регулярным выражением. Это сделало бы регулярное выражение go неправильным при использовании в коде сейчас

import yaml
with open(os.path.join(TEMPLATES_DIR,"regex_template.yml")) as f:
    my_dict = yaml.safe_load(f)

print(my_dict)

{'issuer': 'ABCCorp', 'fields': {'invoice_number': 'INVOICE\\s*(\\S+)', 'invoice_date': 'INVOICE DATE\\s*(\\S+)', 'cusotmer_id': 'CUSTOMER ID\\s*(\\S+)', 'origin': 'ORIGIN\\s*(.*)ETD', 'destination': 'DESTINATION\\s*(.*)ETA', 'sub_total': 'SUBTOTAL\\s*(\\S+)', 'add_gst': 'SUBTOTAL\\s*(\\S+)', 'total_cost': 'TOTAL USD\\s*(\\S+)', 'description_breakdown': '(?s)(DESCRIPTION\\s*GST IN USD\\s*.+?TOTAL CHARGES)', 'package_details_fields': '(?s)(WEIGHT\\s*VOLUME\\s*.+?FLIGHT|ROAD REFERENCE)', 'mawb_hawb'

Как читать правильное регулярное выражение, которое есть у меня в файле yaml? Любая строка, записанная в файле yaml, получает кавычки при чтении в python, потому что это строка?

РЕДАКТИРОВАТЬ:

Основное регулярное выражение в файле yaml:

INVOICE\s*(\S+)

Вывод в dict:

'INVOICE\\s*(\\S+)'

1 Ответ

0 голосов
/ 06 мая 2020

Это слишком долго, чтобы делать комментарий.

Символ backsla sh используется для экранирования специальных символов. Например:

'\n': newline
'\a': alarm

Когда вы используете его перед буквой, не имеющей особого значения, это просто считается backsla sh символ:

'\s': backslash followed by 's'

Но чтобы быть уверенным , всякий раз, когда вы хотите ввести в строку символ backsla sh и не интерпретировать его как начало escape-последовательности, вы удваиваете его:

'\\s': also a backslash followed by a 's'
'\\a': a backslash followed by a 'a'

Если вы используете тип r '' литерал, то backsla sh никогда не интерпретируется как начало escape-последовательности:

r'\a': a backslash followed by 'a' (not an alarm character)
r'\n': a backslash followed by n (not a newline -- however when used in a regex. it will match a newline)

Теперь вот линия вывода:

Когда вы распечатываете эти Python объекты, например:

d = {'x': 'ab\sd'}
print(d)

Python напечатает строковое представление словаря, а строка напечатает: 'ab\\sd'. Если вы только что сделали:

print('ab\sd')

, вы увидите ab\sd. Большая разница.

Почему разница. Посмотрите, имеет ли это смысл:

d = {'x': 'ab\ncd'}
print(d)
print('ab\ncd')

Результаты:

d = {'x': 'ab\ncd'}
ab
cd

Суть в том, что когда вы печатаете Python объект, отличный от строки, он печатает представление объект, показывающий, как бы вы его создали. И если объект содержит строку, и эта строка содержит backsla sh, вы бы удвоили эту backsla sh при вводе.

Update

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

import re

my_dict = {'issuer': 'ABCCorp', 'fields': {'invoice_number': 'INVOICE\\s*(\\S+)', 'invoice_date': 'INVOICE DATE\\s*(\\S+)'}}

fields = my_dict['fields']
invoice_number_re = fields['invoice_number']
m = re.search(invoice_number_re, 'blah-blah INVOICE 12345 blah-blah')
print(m[1])

Печать:

12345

Если вы собираетесь использовать одни и те же регулярные выражения снова и снова, тогда лучше всего их скомпилировать:

import re

my_dict = {'issuer': 'ABCCorp', 'fields': {'invoice_number': 'INVOICE\\s*(\\S+)', 'invoice_date': 'INVOICE DATE\\s*(\\S+)'}}

#compile the strings to regular expressions
fields = my_dict['fields']
for k, v in fields.items():
    fields[k] = re.compile(v)

invoice_number_re = fields['invoice_number']
m = invoice_number_re.search('blah-blah INVOICE 12345 blah-blah')
print(m[1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...