python: 从字符串模板中提取变量
python: extracting variables from string templates
我熟悉使用 Templates 将变量插入字符串的能力,如下所示:
Template('value is between $min and $max').substitute(min=5, max=10)
我现在想知道是否可以反过来。我想获取一个字符串,并使用模板从中提取值,这样我就有了一些包含提取值的数据结构(最好只是命名变量,但字典也可以)。例如:
>>> 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
-- 是否应该接受该字符串以及 min
和 max
是什么?)。
更新 2。 与其制作精确的正则表达式,有时更容易将正则表达式和 "regular" 代码结合起来,如下所示:
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<>.*)', pattern)
match= re.match(pattern, string)
print(match.groupdict()) # output: {'max': '10', 'min': '5'}
behave
module for Behavior-Driven Development provides a few different mechanisms for specifying and parsing templates.
根据模板的复杂程度以及应用的其他需求,您可能会发现其中一个最有用。 (此外,您还可以窃取他们预先编写的代码。)
你可以使用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'}
我熟悉使用 Templates 将变量插入字符串的能力,如下所示:
Template('value is between $min and $max').substitute(min=5, max=10)
我现在想知道是否可以反过来。我想获取一个字符串,并使用模板从中提取值,这样我就有了一些包含提取值的数据结构(最好只是命名变量,但字典也可以)。例如:
>>> 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
-- 是否应该接受该字符串以及 min
和 max
是什么?)。
更新 2。 与其制作精确的正则表达式,有时更容易将正则表达式和 "regular" 代码结合起来,如下所示:
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<>.*)', pattern)
match= re.match(pattern, string)
print(match.groupdict()) # output: {'max': '10', 'min': '5'}
behave
module for Behavior-Driven Development provides a few different mechanisms for specifying and parsing templates.
根据模板的复杂程度以及应用的其他需求,您可能会发现其中一个最有用。 (此外,您还可以窃取他们预先编写的代码。)
你可以使用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'}