14

文字列テンプレートが置換で使用する可能性のあるすべてのキーワード引数のリストを取得したいと思います。

re以外にこれを行う方法はありますか?

私はこのようなことをしたい:

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

私は単純な Mad-lib のようなプログラムを書いており、string.formatまたはTemplate stringsのいずれかでテンプレート置換を実行したいと考えています。「ストーリー」を書き、ユーザーが生成する必要があるすべての「キーワード」(名詞、動詞など) のテンプレート ファイルをプログラムに生成させたいと考えています。正規表現でこれを行うことができることは知っていますが、別の解決策があるかどうか疑問に思っていましたか? 私は、string.format と string テンプレートの代わりにオープンです。

これには解決策があると思いましたが、簡単な検索では見つかりませんでした。私はこの質問を見つけましたが、 pythonを使用した逆テンプレートですが、実際には探しているものではありません。これが で実行できることを再確認するだけreです。

編集:

$$これは「$」のエスケープであり、必要なトークンではないことに注意してください。$$5「$5」にレンダリングする必要があります。

4

7 に答える 7

31

を使用しても問題ない場合は、メソッドを持つstring.format組み込みクラスの使用を検討してください。string.Formatterparse()

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

詳しくはこちらをご覧ください。

于 2012-10-23T19:12:27.463 に答える
11

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', '', '')]

上記のように、${one}中括弧を使用すると、結果のタプルの 3 番目に移動します。

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

したがって、すべてのキーを取得したい場合は、次のようにする必要があります。

>>> [s[1] or s[2] for s in string.Template.pattern.findall('${one} is a $lonely $number.$$') if s[1] or s[2]]
['one', 'lonely', 'number']
于 2013-05-10T17:48:15.723 に答える
4

呼び出しを記録するインストルメント化されたディクショナリまたは defaultdict を使用して一度レンダリングし、要求された内容を確認できます。

from collections import defaultdict
d = defaultdict("bogus")
text%d
keys = d.keys()
于 2012-10-23T19:33:32.630 に答える
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']
于 2012-10-23T19:07:08.520 に答える
0

あなたは試すことができます:

def get_keys(s):
    tokens = filter(lambda x: x[0] == "$", s.split())
    return map(lambda x: x[1:], tokens)
于 2012-10-23T19:10:22.750 に答える
0

なぜ正規表現を避けたいのですか?彼らはこれのために非常にうまく機能します:

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

テンプレート化については、 re.subを確認してください。コールバックを使用して呼び出すと、ほとんどのことを実行できます。

于 2012-10-23T19:10:55.727 に答える
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']
于 2012-10-23T19:13:31.083 に答える