2012-10-23 120 views
8

我想获得一个字符串模板可能用于替换的所有可能的关键字参数的列表。从模板获取密钥

有没有办法做到这一点,而不是重新?

我想要做这样的事情:

text="$one is a $lonely $number." 
keys = get_keys(text) 
# keys = ('one', 'lonely', 'number') 

我正在写一个简单的疯LIB般的程序,我想与任何string.formatTemplate strings执行模板替换。我想编写'故事',让我的程序生成一个用户需要生成的所有'关键字'(名词,动词等)的模板文件。我知道我可以用正则表达式来做到这一点,但我想知道是否有其他解决方案?我打开替代string.format和字符串模板。

我认为会有解决这个问题的方法,但是我没有在快速搜索中遇到它。我确实发现了这个问题,reverse template with python,但它不是我正在寻找的。它只是重申这可以通过re完成。

编辑:

我要指出,$$是“$”一种逃避,而不是令牌我想要的。 $$5应呈现为“$ 5”。

回答

17

如果没关系使用string.format,可以考虑使用内置string.Formatter类具有parse()方法:

>>> from string import Formatter 
>>> [i[1] for i in Formatter().parse('Hello {1} {foo}')] 
['1', 'foo'] 

详情请参阅here

+0

非常符合我的要求。也许我的问题需要解决,但我基本上不想重新发明轮子。谢谢。 – Yann

+0

如果字符串以键开头,则这不起作用。用'{foo} test'试试以上内容 – syntacticmarmalade

+0

@syntacticmarmalade在Python 3.6上对我很好。如果你的意思是列表最后有一个'None',那是因为字符串不能用键结束。你可以过滤'None'的实例。 –

1

尝试str.strip()str.split()一起:

In [54]: import string 

In [55]: text="$one is a $lonely $number." 

In [56]: [x.strip(string.punctuation) for x in text.split() if x.startswith("$")] 
Out[56]: ['one', 'lonely', 'number'] 
+0

** ** $ **是的string.punctuation一部分**,**制作lstrip(” $')**冗余 – volcano

+0

@volcano刚刚检查,你说得对。 –

0

你可以尝试:

def get_keys(s): 
    tokens = filter(lambda x: x[0] == "$", s.split()) 
    return map(lambda x: x[1:], tokens) 
1

为什么你想避免正则表达式?他们工作得很好这一点:

>>> re.findall(r'\$[a-z]+', "$one is a $lonely $number.") 
['$one', '$lonely', '$number'] 

为模板,检查re.sub,它可以与回调被要求做几乎你想要的东西。

+0

我不想避免正则表达式,我只是想知道是否有另一种方式。 – Yann

+0

那么,如果你想要一只脖子长的非洲动物,它肯定有可能拉长一条鳄鱼,但在大多数情况下,用长颈鹿更容易。 – che

0
>>> import string 
>>> get_keys = lambda s:[el.strip(string.punctuation) 
         for el in s.split()if el.startswith('$')] 
>>> get_keys("$one is a $lonely $number.") 
['one', 'lonely', 'number'] 
1

您可以使用记录调用的工具字典或defaultdict来渲染一次,然后检查它所要求的内容。

from collections import defaultdict 
d = defaultdict("bogus") 
text%d 
keys = d.keys() 
5

string.Template类具有用作属性的模式。您可以打印模式,以获得匹配组

>>> print string.Template.pattern.pattern 

    \$(?: 
     (?P<escaped>\$) | # Escape sequence of two delimiters 
     (?P<named>[_a-z][_a-z0-9]*)  | # delimiter and a Python identifier 
     {(?P<braced>[_a-z][_a-z0-9]*)} | # delimiter and a braced identifier 
     (?P<invalid>)    # Other ill-formed delimiter exprs 
    ) 

而对于你的榜样,

>>> string.Template.pattern.findall("$one is a $lonely $number.") 
[('', 'one', '', ''), ('', 'lonely', '', ''), ('', 'number', '', '')]