文字列置換用のカスタム フォーマッタがあります。これは、標準の文字列フォーマッタとは置換フィールドの構文でのみ異なるはずです: の代わりに'{f}'.format(f=123)
('$(f)'.format(f=123)
後者は実際には のようなカスタム フォーマッタ クラスを使用しますshell_formatter.format(...)
)。
新しい構文を使用するために上書きしstring.Formatter.parse
ましたが、最終的に使用している正規表現は私を満足させるものではありません。
質問:
- 正規表現をよりシンプル/読みやすくすることはできますか?
- 私が見逃したフォーマット構文を変更する簡単な方法はありますか?
アップデート
- 正規表現を簡素化し、新しいテストを追加しました。
- 目的は、テンプレートから C ソース コード ファイルを生成することです。
'{f}'
C ではカーリーが過度に使用されているため、構文を使用してもここでは明らかに機能しません。 string.Template
モジュールは複雑なアクセス指定子をサポートしていません (3 番目のテストを参照)。
コードは次のとおりです。
#! /usr/bin/env python3
import string
import re
class ShellFormatter(string.Formatter):
def parse(self, format_string):
for m in re.finditer(
r"""(?: \$ \( ( [^)]+ ) \) ) # the field access specifier
| (
(?:
\n | . (?= \$ \( ) # any one single character before the '$('
)
| (?:
\n | . (?! \$ \( ) # any one single character, except the one before the '$('
)*
)""",
format_string,
re.VERBOSE):
if m.group(1):
yield ('', m.group(1), '', None)
if m.group(2):
yield (m.group(2), None, None, None)
def main():
...
def test():
s = 'ashyudiqhw $(field) fwekojnwe'
ss = 'checking helll kpoqjkf3483297 18934417 hnhfnqi^$&*@&2 1748912$&#^$\n467812\n^$ jfimopw279\nashyudiqhw $(field) fwekojnwe\njjhjhj$(notfield)'
sss = 'const int complex_stuff = $(stuff[0][field1][field2]);'
sf = ShellFormatter()
assert sf.format(s, field='zzz') == 'ashyudiqhw zzz fwekojnwe'
assert sf.format(ss, field='zzz', notfield='xxx') == 'checking helll kpoqjkf3483297 18934417 hnhfnqi^$&*@&2 1748912$&#^$\n467812\n^$ jfimopw279\nashyudiqhw zzz fwekojnwe\njjhjhjxxx'
assert sf.format(sss, stuff=[ { 'field1': { 'field2': '0x1234' } } ]) == 'const int complex_stuff = 0x1234;'
if __name__ == '__main__':
test()
main()