[TextFSM] オプションフラグの仕組みと使い方
はじめに
ntc-templateを編集するために最近調べたので、自分なりに理解した内容を纏める。
参考にした文献は次のとおり。
TextFSM · google/textfsm Wiki · GitHub
21. Parsing command output with TextFSM — Python for network engineers 1.0 documentation
オプション一覧
ちゃんとした説明は公式サイトを参照。
- Filldown
対象Valueの現在行の解析結果が空だったら、前の行の値をコピーする。 - Fillup
対象Valueの前の行の解析結果が空だったら、今の行の値をコピーする。 - Required
このフラグのValueが空だと、今回の行の解析結果はテーブルに格納されない。 - List
値を複数保持する。これが無いと前の値は上書きされる。 - Key
使い道が分からんので今回はパス。
動作確認
作成したTemplate(test.template)を参照し、結果を出力するためのコード。
解析対象のデータも併せて定義している。
import textfsm InputData = ''' 2022_01_01 banana 100 orange 200 carrot 300 2022_12_31 banana 200 ''' with open('test.template') as template: fsm = textfsm.TextFSM(template) result = fsm.ParseText(InputData) print(fsm.header) print(*result, sep='\n')
基本とするTemplate
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record
解析結果はこうなる。
インプットと同じく2~3行目は日付が空欄。
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['', 'orange ', '200'] ['', 'carrot ', '300'] ['2022_12_31', 'banana ', '200']
Filldownオプション
Template
- DateのValueに
Filldown
オプションを付与
Value Filldown Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_01_01', 'orange ', '200'] ['2022_01_01', 'carrot ', '300'] ['2022_12_31', 'banana ', '200'] ['2022_12_31', '', '']
Dataの空欄が埋まった。でも最後に余計な1行が出てきた。
暗黙のEOF Stateのせいだと思われるので次のとおりEOF Stateを明示的に定義して修正。
(このあたりの仕様の話は公式の説明を参照)
Template(EOF Stateを明示的に定義)
- 末尾に
EOF
Stateを追記
Value Filldown Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record EOF
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_01_01', 'orange ', '200'] ['2022_01_01', 'carrot ', '300'] ['2022_12_31', 'banana ', '200']
最後の行が消えました。
Fillupオプション
Template
- DateのValueに
Fillup
オプションを付与
Value Fillup Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_12_31', 'orange ', '200'] ['2022_12_31', 'carrot ', '300'] ['2022_12_31', 'banana ', '200']
最終行の2022_12_31の値が上方向の空欄に反映された。
挙動の仕組み上、今回はEOF Stateを明示する必要なし。
Requiredオプション
Template
- DateのValueに
Required
オプションを付与
Value Required Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_12_31', 'banana ', '200']
RequiredであるDateのValueがない行は格納されなくなった。
Listオプション
説明の前に具体的な活用例を示す。
Continueオプションと併せて使うため、下記の記事も参考にどうぞ。
[TextFSM] Rule Actionsの挙動確認 - るつぼっと
Template
- ItemとQtyのValueに
List
オプションを付与 - 1行目に
Continue.Record
付きのルールを追加
^\dは「行頭が数字」という条件のため今回は日付有りの行が該当 - その他の行は
Record
無し
Value Date (\d+_\d+_\d+) Value List Item (\D+) Value List Qty (\d+) Start ^\d -> Continue.Record ^${Date}\s*${Item}\s*${Qty} ^\s*${Item}\s*${Qty}
結果
['Date', 'Item', 'Qty'] ['2022_01_01', ['banana ', 'orange ', 'carrot '], ['100', '200', '300']] ['2022_12_31', ['banana '], ['200']]
このとおり、同じ日付についてはItemやQtyの値が一つのリストに纏められた。
こういう使い方をするらしい。
と言ってもこれだけじゃ分からないので動作を整理してみる。
動作の流れ
【注意】
以降は文献や動作結果から想像した内容です。誤りがあるかもしれません。
また、説明の都合により次の言葉を独自に定義しています。
- Output Table…Recordアクションにより値が格納される場所
- Buffer…ルールで抽出した値がRecordで格納されるまでに一時保存される場所
1.
1行目のInputが1行目のルールと照合され、合致する。
Recordアクションが取られるが何もBufferされていないため何も格納されない。
2.
Continueアクションに基づき2行目のルールと照合され、合致する。
各Valueに紐づく値がBufferへ格納される。
RecordアクションがないためOutput Tableには格納されない。
3.
2行目のInputが1,2行目のルールと照合され、合致しない。
続いて3行目のルールと照合され、合致する。
各Valueに紐づく値がBufferへ格納される。
※ 今回はList形式のため値が追加される。List形式でない場合は値が上書きされる
RecordアクションがないためOutput Tableには格納されない。
4.
3行目のInputが1,2行目のルールと照合され、合致しない。
続いて3行目のルールと照合され、合致する。
各Valueに紐づく値がBufferへ格納される。
RecordアクションがないためOutput Tableには格納されない。
5.
4行目のInputが1行目のルールと照合され、合致する。
Recordアクションが取られBufferされた値がOutput Tableへ格納される。
6.
Continueアクションに基づき2行目のルールと照合され、合致する。
各Valueに紐づく値がBufferへ格納される。
RecordアクションがないためOutput Tableには格納されない。
7.
Inputを全行読み込んだため最後に暗黙のEOF Stateの処理が走る。
つまり、Bufferされた値がOutput Tableへ格納される。
以上。
こんな動作をしているものと想定してます。