最后,我按照@jonrsharpe的例子给出了解决方案,并在此处提供。它适用于我,除了我需要使用os.path.split来拆分文件夹和文件名,以确保模板中关键字的唯一性。
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
====以下是我的问题。
我将数据存储在不同的目录树中。
可能就像
/parent/folder/$year/$day/$location/$sensor..$freq.$year.$day.dat
或
/parent/folder/$sensor/$year.$day/$sensor.$location.$year.$day.dat
或......
我想定义一个像
这样的函数def parse_kwdict(s, template, keys, kwmark='$'):
do somthing here
return kwdict
这样我就可以从字符串和模板中提取键的值。
例如,
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'}
我的案件要处理的一些注意事项,
关键字的值中有无空格。
模板中的关键字之间总是有字母,点,下划线,斜线等分隔符。
模板中的关键字列在keys
(keyword ='$'+ key)中,它们完全不同。 $freq
和$frequency
这样的关键字不会产生默默无闻。
关键字仅包含字母,不包含特殊字符。
关键字的值包括字母和数字,没有特殊字符,但也可以是''。
关键字可以在模板和字符串中出现一次或多次,也可以不存在。如果关键字出现多次,则字符串中的值相同。
答案 0 :(得分:1)
以下是您可以采取的方法的一般示例;满足您的需求所需的适应性对我来说并不完全清楚。基本上它是从基于$
的模板字符串转换为具有命名捕获组的正则表达式模式,然后使用它从实际路径中提取数据:
>>> 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'}
请注意,字典键必须是唯一的,因此,例如$year
在您的模板中出现两次,您必须想出一些方法来区分这两个值。
答案 1 :(得分:0)
短篇小说:你不能(在一般情况下)可靠地逆转合并,你的第一个例子是明确的:template = 'T$a$b_an_$c'
string = 'This is_an_example'
可以给a='' b='his is'
,a='h' b='is is'
,{ {1}}等等。
长篇故事:
a='hi' b='s is'
后跟$
范围内的单个小写字符,修复了所有剩余的标记a-z
或许其他人).?(){}\:
替换模板中的可替换标记来构建正则表达式,并使用其转义值替换固定部分您可以尝试使用 ungreedy 匹配(.*
代替.*?
)。如果你得到与贪婪搜索完全相同的解决方案,解决方案应该是唯一的 - 更准确地说,我不是很确定,但是无法想象一个例子,它会是错误的
上次修改的最后评论:
.*
)${xxz}
不会使用上述方法给出独特的结果:'/AAA/$a.$b.$c.txt'
可以提供/AAA/x.y.z.t.txt
(gready)或{ 'a' : 'x.y', 'b': 'z', 'c': 't' }
(ungreedy)