2014-12-31 3 views
9

は、フォーマット文字列を考えると? (自分で直接解析することなく)。フォーマット文字列で使用される名前のリストを取得するにはどうすればよいですか?</p> <pre><code>x = "hello %(foo)s there %(bar)s" </code></pre> <p>フォーマット変数の名前を取得する方法はあります:

Regexを使用することはあまり難しくありませんが、これらを取得するより直接的な方法があるのだろうかと思っていました。

+5

それはです[非常に簡単](HTTPS:/ /docs.python.org/2/library/string.html#string.Formatter)新しいスタイルの書式設定に切り替えることができます。 –

+0

実際にはオプションではない、残念ながら – qhfgva

答えて

7

がオーバーライドさ__missing__方法でdictサブクラスを使用して、そこからあなたが欠落しているすべてのフォーマット変数を収集することができます。

class StringFormatVarsCollector(dict): 
    def __init__(self, *args, **kwargs): 
     self.format_vars = [] 

    def __missing__(self, k): 
     self.format_vars.append(k) 
...   
def get_format_vars(s): 
    d = StringFormatVarsCollector()  
    s % d      
    return d.format_vars 
... 
>>> get_format_vars("hello %(foo)s there %(bar)s") 
['foo', 'bar'] 
+0

FWIW、これは私が使用することを決めた方法です。 – qhfgva

3

フォーマットフィールドは、文字列自体ではなく、%演算子にとって重要です。したがって、フィールド名を取得するためにアクセスできるstr.__format_fields__のような属性はありません。

私はRegexを使用して実際にこの場合正しいアプローチだと思います。あなたは簡単に名前を抽出するためにre.findallを使用することができます。

以下
>>> import re 
>>> x = "hello %(foo)s there %(bar)s" 
>>> re.findall('(?<!%)%\(([^)]+)\)[diouxXeEfFgGcrs]', x) 
['foo', 'bar'] 
>>> 

は、パターンの説明です:

(?<!%)    # Negated look-behind to make sure that we do not match %% 
%     # Matches % 
\(    # Matches (
(     # Starts a capture group 
[^)]+    # Matches one or more characters that are not) 
)     # Closes the capture group 
\)     # Matches) 
[diouxXeEfFgGcrs] # Matches one of the characters in the square brackets 
+0

私は、閉じ括弧の後に有効な書式設定文字の1つを探すだろう。 '[diouxXeEfFgGcrs]'はすべきです。 –

+0

そこに、私はすべてのキンクを洗い流したと思う。 :) – iCodez

+0

hello %%%(foo) "'はどうですか? – Kobi

5

あなたは文字列を解析したくない場合、あなたはこの小さな機能を使用することができます。

def find_format_vars(string): 
    vars= {} 
    while True: 
     try: 
      string%vars 
      break 
     except KeyError as e: 
      vars[e.message]= '' 
    return vars.keys() 

>>> print find_format_vars("hello %(foo)s there %(bar)s") ['foo', 'bar']

3

新しいスタイルの文字列フォーマttingにはこの能力があります。解析されたの

from string import Formatter 

f = Formatter() 
x = "hello {foo}s there {bar}s" 
parsed = f.parse(x) 

結果は、この形式のタプルの反復可能になります。
(literal_text、FIELD_NAME、format_spec、変換)

だから、タプルのFIELD_NAMEセクションを引き出すために十分に簡単です:ここで

field_names = [tup[1] for tup in parsed] 

を使用すると、より詳細な情報をご希望の場合はドキュメントだ https://docs.python.org/2/library/string.html#string.Formatter

シングルリスト内包バージョン:

[tup[1] for tup in "hello {foo}s there {bar}s"._formatter_parser()] 
+1

BTWはPython 2で、 'parsed = x._formatter_parse'と同じくらい簡単です。 –

関連する問題

 関連する問題