Splunk Answerの質問How to breakdown TLV (Tag Length Value) formatを無理やり解いた。
ちょっとモヤっとしたので、プログラムっぽくやってみたらできたので、新年一発目の投稿にしました。
TLV
data in TLV format: 0104ABCD0203XYZ0502MQ
01 - Subfield 01
04 - Lenght of Subfield 01
ABCD - Content of Subfield 01
02 - Subfield 02
03 - Length of Subfield 02
XYZ - Content of Subfield 02
05 - Subfield 05
02 - Lenght of Subfield 05
MQ - Content of Subfield 05
ということらしいです。
はじめの回答
| makeresults
| eval _raw="0209MDJXMNZOF0306852024060205
0115300013698746230030658051404101319580514050201060214
0115380013698554359030655053704101319550537060205
0209MDSHRC6H60306851854050215060204
0209MDSIU39OS0306320261060205
0209MPGHON2H60306361705050206060262
0115580013700140787030632036504101319320365060205
0115300013699266920030673054204101319730542060205
0115300013698579543030655264604101319552646060205"
| makemv delim="
" _raw
| stats count by _raw
| table _raw
| rename COMMENT as "this is sample you provide. from here, the logic"
| rex field=_raw "^(?<fn_1>\d\d)(?<fl_1>\d\d)"
| eval sub1=substr(ltrim(_raw,fn_1.fl_1),1,fl_1)
| eval blob_1=fn_1.fl_1.sub1
| eval blob_2=substr(_raw,len(blob_1)+1)
| rex field=blob_2 "^(?<fn_2>\d\d)(?<fl_2>\d\d)"
| eval sub2=substr(blob_2,5,fl_2)
| eval blob_2=fn_2.fl_2.sub2
| eval blob_3=substr(_raw,len(blob_1.blob_2)+1)
| rex field=blob_3 "^(?<fn_3>\d\d)(?<fl_3>\d\d)"
| eval sub3=substr(blob_3,5,fl_3)
| eval blob_3=fn_3.fl_3.sub3
| eval blob_4=substr(_raw,len(blob_1.blob_2.blob_3)+1)
| rex field=blob_4 "^(?<fn_4>\d\d)(?<fl_4>\d\d)"
| eval sub4=substr(blob_4,5,fl_4)
| eval blob_4=fn_4.fl_4.sub4
| eval blob_5=substr(_raw,len(blob_1.blob_2.blob_3.blob_4)+1)
| rex field=blob_5 "^(?<fn_5>\d\d)(?<fl_5>\d\d)"
| eval sub5=substr(blob_5,5,fl_5)
| eval blob_5=fn_5.fl_5.sub5
| foreach fn_*
[eval {<<FIELD>>} = sub<<MATCHSTR>>]
| fields 0*
| rename * as Subfield_*
自分でもよくやったなというくらい繰り返してる。
デバッグしながらやったので、これはこれでありでした。
最初はltrim
を使用してたんだけど、文字列が長いとうまく切り出せなかったりしたので諦め。
substr
の繰り返しになったのは、他のコマンドできっていったら最後05
が5
になったりして、うまくいかなくなりました。なんでだろ
プログラムっぽく
| makeresults
| eval _raw="0209MDJXMNZOF0306852024060205
0115300013698746230030658051404101319580514050201060214
0115380013698554359030655053704101319550537060205
0209MDSHRC6H60306851854050215060204
0209MDSIU39OS0306320261060205
0209MPGHON2H60306361705050206060262
0115580013700140787030632036504101319320365060205
0115300013699266920030673054204101319730542060205
0115300013698579543030655264604101319552646060205"
| makemv delim="
" _raw
| stats count by _raw
| table _raw
| rename COMMENT as "this is sample you provide. from here, the logic"
| eval blob_1=_raw, blob_2="",blob_3="",blob_4="",blob_5="",blob_6="",start=0
| foreach blob_*
[| eval fn_<<MATCHSTR>>=substr(<<FIELD>>,1,2)
| eval fl_<<MATCHSTR>>=substr(<<FIELD>>,3,2)
| eval sub<<MATCHSTR>>=substr(<<FIELD>>,5,fl_<<MATCHSTR>>)
| eval <<FIELD>>=fn_<<MATCHSTR>>.fl_<<MATCHSTR>>.sub<<MATCHSTR>>
| eval start=start+len(<<FIELD>>)
| eval count=<<MATCHSTR>> + 1
| eval blob_{count}=substr(_raw,start+1)]
| foreach fn_*
[ eval {<<FIELD>>} = sub<<MATCHSTR>>]
| fields 0*
| rename * as Subfield_*
foreach
でループするために、最初にeval
で変数を作っているところがプログラムっぽい。
あと、ループの中の eval start=start+len(<<FIELD>>)
のところとかも、そのままカウンター処理してる。
| eval blob_{count}=substr(_raw,start+1)
なんかは次のフィールドに移れないので、名前をこのように作っている。
うまくいってよかった
まとめ
意外とSplunkでループできるかもしれない。 他のプログラム言語のfor
の使い方がこのようにできるので。
でも、なんに使おう