我熟悉使用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'}
这可能吗?
答案 0 :(得分:8)
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。有时更容易将正则表达式和“常规”代码组合在一起,而不是制作精确的正则表达式:
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()
,可选的块合并,以及每个块的独立处理(使用正则表达式和其他方法)。
答案 1 :(得分:2)
不可能完全扭转替代。问题是某些字符串不明确,例如
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'}
答案 2 :(得分:0)
行为驱动开发的behave
module提供了一些不同的机制来指定和parsing templates.
根据模板的复杂程度以及应用的其他需求,您可能会发现其中一个或另一个最有用。 (另外,你可以窃取他们预先编写的代码。)
答案 3 :(得分:0)
您可以使用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))
给出: {&#39; min&#39;:&#39; 5&#39;,&#39; max&#39;:&#39; 10&#39;}