簡體   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