期望的结果:
我想要一个解析器函数,它接受一串“指令”。
该字符串将使用 string.split(";")
进行分割并去除空格。我想检查每个“chop”是否与一堆(10+)正则表达式匹配。每个表达式还具有捕获组定义的值,稍后我将使用这些值来“执行命令”。
问题:
我目前有一个又长又复杂的 if、elseif、else 语句,这是非常不可取的,因为它使我的代码更难管理,也更难让其他人阅读。
到目前为止的想法:
基本上,我想使用字典来模拟 switch 语句。但我对正则表达式的经验很少,我能够做出正确的“表达式”来捕获“指令”中我想要的内容。但我对pythons正则表达式包的工作原理很不熟悉。
朝着正确方向迈出的一步已经是一个函数,其中给定单个字符串和正则表达式的列表或字典,该函数将返回匹配的正则表达式。
示例代码:(请原谅缩进:))
class PreparedConstraintsCollection(ConstraintsCollectionABC):
not_pattern = re.compile("^not([-+]*[0-9]+)$")
ex_pattern = re.compile("^ex([-+]*[0-9]+)$")
more_pattern = re.compile("^>([-+]*[0-9]+)$")
less_pattern = re.compile("^<([-+]*[0-9]+)$")
interval_pattern = re.compile("^([-+]*[0-9]+)<x<([-+]*[0-9]+)$")
def parse_constraints_string(self, restriction_string: str) -> set:
"""
The overly-complex function to parse the restriction control sequence strings
Control Sequence Meaning Explanation
---------------------------------------------------------------------------------------------
+ Positive only Allow only positive values
- Negative only Allow only negative values
notX Not X value Do not allow values X
exX Must be X Only allow values X
>X More then X Values must be more then X
<X Less then X Values must be less then X
M<x<N Interval M, N Must be more then M but less then N
:param restriction_string: a string with control sequences
:return: return the gathered restriction instances, conserve only unique
"""
gathered_constraints = set()
for control_seq in restriction_string.split(";"):
stripped = control_seq.strip().replace(" ", "")
if stripped == "":
continue
elif stripped == "+":
gathered_constraints.add(res_gallery.PositiveConstraint())
elif stripped == "-":
gathered_constraints.add(res_gallery.NegativeConstraint())
elif self.not_pattern.match(stripped):
searched = re.search(self.not_pattern, stripped)
param = float(searched.group(1))
gathered_constraints.add(res_gallery.NotExactValueConstraint(param))
elif self.ex_pattern.match(stripped):
searched = re.search(self.ex_pattern, stripped)
param = float(searched.group(1))
gathered_constraints.add(res_gallery.ExactValueConstraint(param))
elif self.more_pattern.match(stripped):
searched = re.search(self.more_pattern, stripped)
param = float(searched.group(1))
gathered_constraints.add(res_gallery.GreaterThanConstraint(param))
elif self.less_pattern.match(stripped):
searched = re.search(self.less_pattern, stripped)
param = float(searched.group(1))
gathered_constraints.add(res_gallery.LessThanConstraint(param))
elif self.interval_pattern.match(stripped):
searched = re.search(self.interval_pattern, stripped)
param1, param2 = float(searched.group(1)), float(searched.group(2))
gathered_constraints.add(res_gallery.IntervalConstraint(param1, param2))
else:
raise ValueError("Restriction string could not be parsed!")
return gathered_constraints
最佳答案
解析器的一种可能性是编写一个标记生成器,它将创建所有语句和找到的类型的嵌套列表:
第一步是创建语法并对输入字符串进行标记:
import re
import collections
token = collections.namedtuple('token', ['type', 'value'])
grammar = r'\+|\-|\bnot\b|\bex\b|\>|\<|[a-zA-Z0-9_]+'
tokens = {'plus':'\+', 'minus':'\-', 'not':r'\bnot\b', 'ex':r'\bex\b', 'lt':'\<', 'gt':'\>', 'var':'[a-zA-Z0-9_]+'}
sample_input = 'val1+val23; val1 < val3 < new_variable; ex val3;not secondvar;'
tokenized_grammar = [token([a for a, b in tokens.items() if re.findall(b, i)][0], i) for i in re.findall(grammar, sample_input)]
现在,tokenized_grammar
存储文本中所有标记化语法出现的列表:
[token(type='var', value='val1'), token(type='plus', value='+'), token(type='var', value='val23'), token(type='var', value='val1'), token(type='lt', value='<'), token(type='var', value='val3'), token(type='lt', value='<'), token(type='var', value='new_variable'), token(type='var', value='ex'), token(type='var', value='val3'), token(type='var', value='not'), token(type='var', value='secondvar')]
token 类型和值可以作为对象访问:
full_types = [(i.type, i.value) for i in tokenized_grammar]
输出:
[('var', 'val1'), ('plus', '+'), ('var', 'val23'), ('var', 'val1'), ('lt', '<'), ('var', 'val3'), ('lt', '<'), ('var', 'new_variable'), ('var', 'ex'), ('var', 'val3'), ('var', 'not'), ('var', 'secondvar')]
要实现 switch
-case
语句的流程,您可以创建一个字典,其中每个键是标记的类型,值是一个类存储后面要添加的相应值和方法:
class Plus:
def __init__(self, storing):
self.storing = storing
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.storing)
class Minus:
def __init__(self, storing):
self.storing = storing
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.storing)
...
然后,创建字典:
tokens_objects = {'plus':Plus, 'minus':Minus, 'not':Not, 'ex':Ex, 'lt':Lt, 'gt':Lt, 'var':Variable}
然后,您可以迭代tokenized_grammar
,并为每次出现创建一个类对象:
for t in tokenized_grammar:
t_obj = token_objects[t.type](t.value)
关于python - 正则表达式相关,python中的switch语句模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48690874/