JSONなログから取り出す時(?ms)
を使うようになってきたので、忘備録をかねて
Splunk公式はここ
wikipediaはここ
本家によるとオプションは
- i for PCRE_CASELESS
- m for PCRE_MULTILINE
- s for PCRE_DOTALL
- x for PCRE_EXTENDED
始めに(?ms)
といった形で使う
i
大文字と小文字を区別せずにマッチを行う
| makeresults
| eval _raw="1584081083.114 ABC-12345,158 4081089.114 DEF-678910"
| rex "(?i)(?<result>abc)"
result |
---|
ABC |
ということで大文字・小文字関係なくマッチしてくれる。 |
m
対象の文字列を複数行として扱う
s
メタ文字(.)が改行にマッチ
| makeresults
| eval _raw="{\"studentInfo\": {
\"name\": \"Apple\",
\"id\": \"57\",
\"batch\": \"2006\",
\"subjects\": {
\"subject1\": \"English\"
}}}"
| rex "(?ms)subjects.*{.*\"(?<subjects>.*)\""
result |
---|
English |
(?m)
がないと正規表現は1行毎評価される。
正確には^
と$
が行頭・行末ではなく、文字列の最初と最後になる。
(?s)
と一緒に使うと、行と関係なしにマッチングできる。
今回のsubjects.*{.*\"(?<subjects>.*)\"
で
{.*\"
が途中の\"
をすっ飛ばしているのがGreedy
マッチングの特徴。
{.*?\"
にすると最初の\"
で止まってしまう。これはLazy
マッチング。
x
パターンの中の空白やコメントを無視する
| makeresults
| eval _raw="{\"studentInfo\": {
\"name\": \"Apple\",
\"id\": \"57\",
\"batch\": \"2006\",
\"subjects\": {
\"subject1\": \"English\"
}}}"
| rex "(?msix)subjects.*{.*\"(?<subjects>e n g l i s h)\""
result |
---|
English |
その他
- J (PCRE_INFO_JCHANGED)
- x (PCRE_EXTENDED)
- U (PCRE_UNGREEDY)
cf. https://www.php.net/manual/ja/reference.pcre.pattern.modifiers.php
J
サブパターンで重複した名前を使用できるようになります。
x
エスケープするか 文字クラスの内部を除き、 パターンの空白文字は完全に無視されます。 文字クラスの外にあって、かつエスケープされていない # と次の改行文字の間の文字も無視されます。
| makeresults
| eval _raw="test1 test2
test3"
| rex "(?Jx)(?<result>\w+)\s*(?<result>\w+)\s*(?<result>\w+)#this is comment#"
動作検証のためだけに作ったので、あまり意味はないです。
(?J)
のオプションがないと同じサブパターン名は使えない。
(?x)
のオプションをつけると、#コメント#
が使える。
(?J)
を指定すると、rex
のmax_match
が効かなくなるようで注意が必要です。
U
量指定子の「貪欲さ」が反転します。
| makeresults
| eval _raw="test1 test2
test3"
| rex "(?U)(?<result>\w+)"
Uオプションあり | Uオプションなし |
---|---|
t | test1 |
と反転している。 |
(?P=NAME)
index=_internal | head 1 | fields _raw
| eval _raw="Hello someone@example.com
If you Are you interested in this site?
<h2><a href=\"http://someMalicious.com/\">http://www.yourfavorate.example.com/</a></h2>
"
| rex max_match=0 "(?msix) # 複数行でマッチさせるため盛り沢山
\w+@(?P<mail_domain>[\w.]+)\b # メールアドレスのドメインを抽出
.* # メール本文中の他の箇所
(?<malicious_site>(?P=mail_domain)) # メールアドレスのドメインを使って詐称している場合、キャプチャーしてくれるはず"
| search malicious_site=*
ものすごくコンセプト紹介のために作ってみた。
(?P=NAME)
はrex
でフィールド抽出したフィールド名(NAME)の中身で検索が可能
悪性メールだと、受信者へのメールアドレスへの返信を装い、リンク先に表示されているHPのドメインはメールドメインから生成しているものもある。
その場合、こんな感じたと検知が可能(じゃないかな〜 )
props.confにおけるLINE_BREAKERについて
Splunk>Answersで回答する際、Splunk Add-on Builderで確認していたら、結果として
SHOULD_LINEMERGE = false
LINE_BREAKER = Line.*[\r\n]\[.*\]\*.*([\r\n])\[.*\]Line
になった。(間違えていたので修正)
この結果からすると、LINE_BREAKER
は(?msU)
のオプション自動的に設定されると考えるとわかりやすい。
解説
行末でイベントを分けたかったので、([\r\n])
を基準で考える
*
を含む行は\[.*\]\*.*
Line
を含む行は\[.*\]Line
とLine.*
これを順番に並べたのが設定
Greedyマッチが反転しているので?
がいらない
あっているかな
オプションを解除する
https://answers.splunk.com/answers/814182/extract-data-from-a-txt-file.html
でえらい苦労してやってみてわかりました。
[merge_csv]
REGEX = (?-ms)(?<Agent_Name>\w.*)\s+(?<Canal>\d+)\s+?(?<Ramal>\d+)\s+?(?<Id_do_Logger>\d+)\s+?(?<Dia>[\d\/]+)\s+?(?<Chamadas>\d+)
MV_ADD = true
コマンドの結果をそのまま取り込んで、行で分割しないところからフィールドを抽出している。
(?-ms)
とすることで、無理やり行を認識させている。
気付いたら2時間やっていた・・・
オプションではないけど
- コメント
(?# コメントがかける)
| makeresults
| eval _raw="some text (aaa(b(c1)(c2)d)e)(test) more text"
| rex max_match=0 "(?<match>\([^()]*\))(?# コメント)"
-
(?R)または(?1)(?2)
再帰的に一致する。ただmax_match
オプションがあるので使い方がよくわからなかった。 -
独占的
+
量識別子
| makeresults
| eval _raw="some text (aaa(b(c1)(c2)d)e)(test) more text"
| rex "\((?<match>.*+)\)(?# 一致しないよ)"
?
と?
をつけない挙動は理解していたけど、奥が深い
正規表現のコストってSPLだとあんまり気にしないけどSEDCMD
で使う場合は気にする必要がある。
まとめ
Splunkだとprops.confやtransforms.conf、rex
、replace()
あとregex
とか正規表現を使う場面が多々ある。
オプションを使うと結構簡単にマッチングできる時があるので、活用してみてください。