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とか正規表現を使う場面が多々ある。
オプションを使うと結構簡単にマッチングできる時があるので、活用してみてください。