簡體   English   中英

python:從字符串模板中提取變量

[英]python: extracting variables from string templates

我熟悉使用模板將變量插入字符串的功能,如下所示:

Template('value is between $min and $max').substitute(min=5, max=10)

我現在想知道的是,是否可以反過來。 我想取一個字符串,並使用模板從中提取值,以便我有一些包含提取值的數據結構(最好只是命名變量,但dict很好)。 例如:

>>> string = 'value is between 5 and 10'
>>> d = Backwards_template('value is between $min and $max').extract(string)
>>> print d
{'min': '5', 'max':'10'}

這可能嗎?

這叫做正則表達式

import re
string = 'value is between 5 and 10'
m = re.match(r'value is between (.*) and (.*)', string)
print(m.group(1), m.group(2))

輸出:

5 10

更新1.名稱可以提供給組:

m = re.match(r'value is between (?P<min>.*) and (?P<max>.*)', string)
print(m.group('min'), m.group('max'))

但是這個功能並不經常使用,因為通常有一個更重要方面的問題:如何准確捕獲你想要的東西(這個特殊情況並不是什么大問題,但即使在這里:如果字符串value is between 1 and 2 and 3怎么辦? value is between 1 and 2 and 3 - 應該接受字符串以及minmax多少?)。


更新2.有時更容易將正則表達式和“常規”代碼組合在一起,而不是制作精確的正則表達式:

m = re.match(r'value is between (?P<min>.*) and (?P<max>.*)', string)
try:
    value_min = float(m.group('min'))
    value_max = float(m.group('max'))
except (AttributeError, ValueError):  # no match or failed conversion
    value_min = None
    value_max = None

當你的文本包含許多要處理的塊(如不同類型的引號中的短語)時,這種組合方法尤其值得記住:在棘手的情況下,定義單個正則表達式以處理塊的分隔符和內容比定義幾個更難諸如text.split()類的步驟,可選的塊組合以及每個塊的獨立處理(使用正則表達式和其他方法)。

完全取消替換是不可能的。 例如,問題是某些字符串不明確

value is between 5 and 7 and 10

將有兩種可能的解決方案: min = "5", max = "7 and 10"min = "5 and 7", max = "10"

但是,您可以使用正則表達式獲得有用的結果:

import re

string = 'value is between 5 and 10'
template= 'value is between $min and $max'

pattern= re.escape(template)
pattern= re.sub(r'\\\$(\w+)', r'(?P<\1>.*)', pattern)
match= re.match(pattern, string)
print(match.groupdict()) # output: {'max': '10', 'min': '5'}

行為驅動開發的behave模塊提供了一些用於指定和解析模板的不同機制

根據模板的復雜程度以及應用程序的其他需求,您可能會發現其中一個或另一個最有用。 (另外,你可以竊取他們預先編寫的代碼。)

您可以使用difflib模塊比較兩個字符串並提取所需的信息。

https://docs.python.org/3.6/library/difflib.html

例如:

import difflib

def backwards_template(my_string, template):
    my_lib = {}
    entry = ''
    value = ''

    for s in difflib.ndiff(my_string, template):
        if s[0]==' ':
            if entry != '' and value != '':
                my_lib[entry] = value 
                entry = ''
                value = ''   
        elif s[0]=='-':
            value += s[2]
        elif s[0]=='+':
            if s[2] != '$':
                entry += s[2]

    # check ending if non-empty
    if entry != '' and value != '':
        my_lib[entry] = value

    return my_lib

my_string = 'value is between 5 and 10'
template = 'value is between $min and $max'     

print(backwards_template(my_string, template))

給:{'min':'5','max':'10'}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM