LoginSignup
0
0

More than 3 years have passed since last update.

Splunkでプログラムっぽいことをする

Posted at

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

ということらしいです。

はじめの回答

TLVdecode.SPL
 | 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の繰り返しになったのは、他のコマンドできっていったら最後055になったりして、うまくいかなくなりました。なんでだろ :question:

プログラムっぽく

TLVlikeProgram.SPL
| 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)なんかは次のフィールドに移れないので、名前をこのように作っている。
うまくいってよかった :sweat:

まとめ

意外とSplunkでループできるかもしれない。 他のプログラム言語のforの使い方がこのようにできるので。
でも、なんに使おう :question:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0