从Python中的字符串和模板获取关键字值
最后,我得到了@jornsharpe示例的解决方案,我在这里展示了它。它适用于我,只是我需要使用os.path.split分割文件夹和文件名,以确保模板中关键字的唯一性从Python中的字符串和模板获取关键字值,python,python-2.7,Python,Python 2.7,最后,我得到了@jornsharpe示例的解决方案,我在这里展示了它。它适用于我,只是我需要使用os.path.split分割文件夹和文件名,以确保模板中关键字的唯一性 def parse_kwdict(s, template, keys, kwmark='$'): kw2rekw = {key:'(?P<'+key+'>.*)' for key in keys} pattern = replace(template, kw2rekw, kwmark=kwmark)
def parse_kwdict(s, template, keys, kwmark='$'):
kw2rekw = {key:'(?P<'+key+'>.*)' for key in keys}
pattern = replace(template, kw2rekw, kwmark=kwmark)
return re.match(pattern, s).groupdict()
def replace(template, kwdict, kwmark='$'):
name = template
for key, val in kwdict.iteritems():
if val is not None:
name = name.replace(kwmark+key, str(val))
return name
这样我就可以从字符串和模板中提取键的值
比如说,
template = '/parent/folder/$sensor/$year.$day/$freq/$sensor.$location.$year.$day.dat'
keys = ['year', 'day', 'location', 'sensor', 'freq'] # keywords in the template
s = '/parent/folder/SensorA/2011.123/5Hz/SensorA.E.2011.123.dat'
kwdict = parse_kwdict(s, template, keys)
产生
kwdict = {'year':2011, 'day':123, 'location':'E', 'sensor':'SensorA', 'freq':'5Hz'}
我的案子需要处理的一些笔记
键中(关键字=“$”+键),它们完全不同。不会有像$freq
和$frequency
这样的关键词会让人感到模糊
template='T$a$b\u an\u$c'
string='这是一个示例'
可以给出a='b='his'
,a='h'b='is'
,a='hi b='s'
,等等
长话短说:
- 首先需要解析模板以识别固定部分和可替换令牌:可替换令牌是
,后跟一个小写字符,范围为$
,其余的都是固定的a-z
- 然后您需要转义固定部分中的所有特殊字符(至少
可能还有其他字符)?(){}\:
- 然后,通过将模板中的可替换标记替换为
,并将固定部分替换为其转义值来构建正则表达式*
- 如果字符串与正则表达式匹配,则应该给出一个可能的映射(可能还有其他映射)小心:可能还有其他可能性
*?
而不是*
)。如果你得到了与贪婪搜索完全相同的解决方案,那么这个解决方案应该是唯一的——更确切地说,我不确定这一点,但无法想象一个例子会是错误的
上次编辑的最后备注:
- 如果关键字不是单个字母,您必须指定如何识别它们(shell设计人员设想的
不仅仅是偶然的)${xxz}
- 模板
不会使用上述方法给出唯一的结果:'/AAA/$a.$b.$c.txt'
可以给出/AAA/x.y.z.t.txt
(gready),或{'a':'x.y','b':'z','c':'t'}
(ungreedy){'a':'x','b':'y','c':'z.t'}
- 以下是您可以采取的方法的一般示例;我不完全清楚需要多少调整才能满足您的需求。基本上,它是从基于
$
的模板字符串转换为带有命名捕获组的正则表达式模式,然后使用该模式从实际路径提取数据:
>>> import re
>>> template = '/parent/folder/$freq/$name.dat' # base template
>>> parts = {
'freq': r'(?P<freq>\d+Hz)', # one or more digits then Hz
'name': r'(?P<name>[a-z]{3,8})', # three to eight lowercase letters
} # patterns for the parts of the template
>>> pattern = re.sub(
r'\$([^/.]+)', # dollar followed by characters excluding / and .
lambda match: parts[match.group(1)],
template
) # re.sub creates the pattern to match the actual path
>>> pattern
'/parent/folder/(?P<freq>\\d+Hz)/(?P<name>[a-z]{3,8}).dat'
>>> re.match(
pattern,
'/parent/folder/5Hz/hello.dat'
).groupdict() # re.match extracts the appropriate data
{'freq': '5Hz', 'name': 'hello'}
>>重新导入
>>>template='/parent/folder/$freq/$name.dat'#基本模板
>>>零件={
“频率”:r'(?P\d+Hz)#一个或多个数字,然后是Hz
'name':r'(?P[a-z]{3,8}),#三到八个小写字母
}#模板各部分的图案
>>>模式=re.sub(
r“\$([^/]+)”,#美元后跟不包括/和的字符。
lambda匹配:零件[匹配组(1)],
模板
)#re.sub创建模式以匹配实际路径
>>>图案
“/parent/folder/(?P\\d+Hz)/(?P[a-z]{3,8}).dat”
>>>复赛(
图案
“/parent/folder/5Hz/hello.dat”
).groupdict()#re.match提取适当的数据
{'freq':'5Hz','name':'hello'}
请注意,字典键必须是唯一的,因此,如果模板中出现两次(
$year
),则您必须想出一些方法来区分这两个值。您实际上想要实现什么?为什么不使用常规的repr
格式,您可以使用ast.literal\u eval
轻松解析该格式?@jornsharpe我想我的第一个关于从模板进行正向替换的说明让您感到困惑。我需要的是,当我有一个字符串、一个模板和模板中的关键字列表时,如何从字符串中获取关键字的值?同样,目的是什么?您尝试过什么,到底有什么问题?@Dr.Lee您希望如何可靠地逆转它?以扩展字符串“his”为例-是重新模板化的版本“$bis”还是“$a”?根据给定的条件,可能有很多答案。假设s='这是一个示例。
,template='T$a$b'an'c'
,而kwdict的键是['a','b','c']
,答案可以是{'a':'his','b':'is','c':'example.}
正如你提到的,答案是{'a':'h','b':'is','c':'example.}
也是正确的thx@SergeBallesta我更新了我的问题,去掉了一些模糊之处。
>>> import re
>>> template = '/parent/folder/$freq/$name.dat' # base template
>>> parts = {
'freq': r'(?P<freq>\d+Hz)', # one or more digits then Hz
'name': r'(?P<name>[a-z]{3,8})', # three to eight lowercase letters
} # patterns for the parts of the template
>>> pattern = re.sub(
r'\$([^/.]+)', # dollar followed by characters excluding / and .
lambda match: parts[match.group(1)],
template
) # re.sub creates the pattern to match the actual path
>>> pattern
'/parent/folder/(?P<freq>\\d+Hz)/(?P<name>[a-z]{3,8}).dat'
>>> re.match(
pattern,
'/parent/folder/5Hz/hello.dat'
).groupdict() # re.match extracts the appropriate data
{'freq': '5Hz', 'name': 'hello'}