从YAML文件解析正则表达式会增加额外的\



我有一堆正则表达式,用来从文本文档中抓取许多特定字段。当直接在python脚本中使用时,这些都可以很好地工作。

但我想把它们放在一个YAML文件中,然后从那里阅读。它看起来是这样的:

# Document file for Regular expression patterns for a company invoice
---
issuer: ABCCorp
fields:
invoice_number: INVOICEs*(S+)
invoice_date: INVOICE DATEs*(S+)
cusotmer_id: CUSTOMER IDs*(S+)
origin: ORIGINs*(.*)ETD
destination: DESTINATIONs*(.*)ETA
sub_total: SUBTOTALs*(S+)
add_gst: SUBTOTALs*(S+)
total_cost: TOTAL USDs*(S+)
description_breakdown: (?s)(DESCRIPTIONs*GST IN USDs*.+?TOTAL CHARGES)
package_details_fields: (?s)(WEIGHTs*VOLUMEs*.+?FLIGHT|ROAD REFERENCE)
mawb_hawb: (?s)((FLIGHT|ROAD REFERENCE).*(MAWB|MASTER BILL)s*.+?GOODS COLLECTED FROM)

当我在python中使用pyyml检索它时,它在它周围添加了一个字符串引号(这很好,因为我稍后可以添加r''(,但我看到它还在正则表达式之间添加了额外的\in。这将使正则表达式在现在的代码中使用时出错

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文件中读取正确的正则表达式?在python中读取时,是否有任何在yaml文件中编写的字符串会在其周围加上引号,因为这是一个字符串?

编辑:

yaml文件中的主要正则表达式是:

INVOICEs*(S+)

dict中的输出为:

'INVOICE\s*(\S+)'

这太长了,不能作为注释。

反斜杠字符用于转义特殊字符。例如:

'n': newline
'a': alarm

当你在一个没有特殊含义的字母之前使用它时,它只是被当作一个反斜杠字符:

's': backslash followed by 's'

但可以肯定的是,每当你想在字符串中输入一个反斜杠字符,而不是将其解释为转义序列的开头时,你可以将其加倍:

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

如果使用r"类型的文字,则反斜杠永远不会被解释为转义序列的开头:

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': 'absd'}
print(d)

Python将打印字典的字符串表示,字符串将打印:CCD_ 1。如果你只是这样做:

print('absd')

你会看到absd。差别很大。

为什么不同。看看这是否有意义:

d = {'x': 'abncd'}
print(d)
print('abncd')

结果:

d = {'x': 'abncd'}
ab
cd

最重要的是,当你打印一个Python对象而不是字符串时,它会打印一个对象的表示,显示你是如何创建它的。如果对象包含一个字符串,而该字符串包含一个反斜杠,你在输入它时会加倍使用该反斜杠。

更新

要处理您的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])

最新更新