繁体   English   中英

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

[英]Parsing Regular expression from YAML file adds extra \

我有一堆正则表达式,用于从文本文档中抓取大量特定字段。 当直接在 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)

当我在 python 中使用 pyyml 检索它时,它会在其周围添加一个字符串引号(这没关系,因为我可以稍后添加 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+)

字典中的 Output 是:

'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': '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 object 而非字符串时,它会打印 object 的表示形式,显示您将如何创建它。 如果 object 包含一个字符串并且该字符串包含一个反斜杠,那么您在输入它时会加倍该反斜杠。

更新

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM