[TextFSM] 予約済みStateの仕組みと使い方
はじめに
ntc-templateを編集するために最近調べたので、自分なりに理解した内容を纏める。
参考にした文献は次のとおり。
TextFSM · google/textfsm Wiki · GitHub
21. Parsing command output with TextFSM — Python for network engineers 1.0 documentation
準備
動作確認用のコード。 解析対象のデータも併せて定義している。
import textfsm InputData = ''' 2022_01_01 banana 100 orange 200 2022_12_31 banana 200 carrot 300 ''' 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,4行目は日付が空欄。
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['', 'orange ', '200'] ['2022_12_31', 'banana ', '200'] ['', 'carrot ', '300']
動作確認
TextFSMには下記の予約済みStateが存在する。それぞれの動作を確認する。
- Start
- EOF
- END
Start State
定義必須のState。
インプット行との照合はこのStateの1行目のRuleから始まる。
ここでは次の2つの動作を確認する。
- Start Stateを定義しない場合
- State以外のStateを追加定義した場合
Template(State Stateを未定義)
- Startの代わりに
Test1
という名称でStateを定義
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Test1 ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> Record
結果
textfsm.parser.TextFSMTemplateError: Missing state 'Start'.
必須のStateがないためErrorで処理が止まった。
Template(他のStateを追加定義)
Test1
,Test2
というStateを定義
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Test1 ^\s*${Item}\s*${Qty} -> Record Start ^${Date}\s*${Item}\s*${Qty} -> Record Test2 ^\s*${Item}\s*${Qty} -> Record
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_12_31', 'banana ', '200']
日付入りの行のみ出力された。
処理はStart Stateから始まり、かつ他のStateへは飛ばないためこうなる。
※ 後ほど確認するState Transition Actionを使えば他のStateへ飛べる
EOF State
インプットの全行について処理を終えた後に自動的に作動するState。
明示的に定義しなかった場合、下記の暗黙のEOF Stateが作動する。
EOF ^.* -> Record
これは今現在収集している情報をRecordするという意味を持つ。
ここでは次の2つの動作を確認する。
- 暗黙のEOF State
- 明示的なEOF State
Template(暗黙のEOF State)
- ほぼ元々と同じ形だが、最後のルールにRecordがない点に注目
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty}
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_12_31', 'banana ', '200'] ['', 'carrot ', '300']
日付入りの行だけが出力されると思いきや、4行目のcarrot,300
も出てきた。
^\s*${Item}\s*${Qty}
はRecordしないもののItem,QtyのValueを収集しており、
それが暗黙のEOF Stateによって出力されるためこうなる。
このあたりの挙動は下記の記事でも確認している。
[TextFSM] Rule Actionsの挙動確認 - るつぼっと
Template(明示的なEOF State)
- 最後のルールにRecordがない
- 新たに
EOF
Stateを定義
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} EOF
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['2022_12_31', 'banana ', '200']
先ほどと違い、日付入りの行だけが出力された。
EOF Stateを明示的に定義した場合、先ほどの暗黙的な動作が
取られないためこのような結果となる。
END State
このStateが作動した時点で解析処理を終了するState。
未解析のインプット行が残っていても終了させる。
Template
- 2行目のルールを
Record
からEND
へ変更
Value Date (\d+_\d+_\d+) Value Item (\D+) Value Qty (\d+) Start ^${Date}\s*${Item}\s*${Qty} -> Record ^\s*${Item}\s*${Qty} -> END END
結果
['Date', 'Item', 'Qty'] ['2022_01_01', 'banana ', '100'] ['', 'orange ', '200']
2行目までが解析および出力された。
どうやらEND StateにはRecordアクションも含まれるようだ。