0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Splunk: ワイルドカード・正規表現での検索におけるヒット条件毎の統計

Posted at

必要な機会があったのでメモ。

実施環境: Splunk Free 8.2.2
前置き

文字列の検索において、条件毎のヒット数を算出することを考えます。
文字列が固定であれば、以下のように stats コマンドを使用することで容易に実現できます。

Splunk
| makeresults count=10
| streamstats count AS CNT
| eval NUM = CNT % 3
| eval STR = "A" + NUM
| where STR = "A1" OR STR = "A2"
| stats count BY STR

スクリーンショット 2022-02-06 22.12.49.png

では、この条件がワイルドカードや正規表現を含むものであればどうでしょうか。

やりたいこと

以下のようなデータを考えます。

STR
one
two
three
four
five
Splunk
| inputlookup "test_data.csv" 

スクリーンショット 2022-02-06 22.09.02.png

検索条件は「 t で始まる文字列」「 e で終わる文字列」の2つを指定します。

STR
t*
*e
Splunk
| inputlookup "test_search.csv" 

スクリーンショット 2022-02-06 22.16.28.png

上記のデータにおいて「 t で始まる文字列」は2つ、「 e で終わる文字列」は3つあります。
この数字を導出することを目指します。

単純に検索すると

まずは単純に format コマンドで検索条件を組み立てて search コマンドで検索してみます。
where コマンドを使用しないのは where コマンドだとワイルドカードをそのまま利用できないためです。

Splunk
| inputlookup "test_data.csv"
| search
    [
      | inputlookup "test_search.csv"
      | format
    ]

スクリーンショット 2022-02-06 22.16.14.png

STR
one
two
three
five

上記の結果をいろいろこねくり回してみましたが、この方針で目的を達成するのは難しそうです。
何が悪いのかを考えると、「どの条件でヒットしたのかが結果から判断できない」ということに気づきます。

以下のように条件毎にサーチ文を作って合成するという方法も思いつきますが、汎用性が無さすぎます。

Splunk
| inputlookup "test_data.csv"
| search
    [
      | inputlookup "test_search.csv"
      | head 1
      | format
    ]
| eval STR_SEARCH = "t*"
| stats count BY STR_SEARCH
| append
    [
      | inputlookup "test_data.csv"
      | search
          [
            | inputlookup "test_search.csv"
            | tail 1
            | format
          ]
      | eval STR_SEARCH = "*e"
      | stats count BY STR_SEARCH
    ]
STR_SEARCH count
t* 2
*e 3

スクリーンショット 2022-02-13 13.30.38.png

解決方法

いろいろ考えた結果、以下の方法に行き着きました。

Splunk
| inputlookup "test_data.csv"
| join max=0
    [
      | inputlookup "test_search.csv"
      | eval STR_SEARCH = STR
      | eval STR_SEARCH_R = replace(STR,"\*","%")
      | fields STR_SEARCH, STR_SEARCH_R
    ]
| where like(STR, STR_SEARCH_R)
| stats count BY STR_SEARCH
STR_SEARCH count
*e 3
t* 2

スクリーンショット 2022-02-13 13.33.16.png

ポイントは以下の2点です。

  • join コマンドの max オプションを使用して検索対象と検索条件の組を全て書き出す

  • where コマンドの like 関数を使用して、組毎に検索を実施する

ポイントの1点目ですが、 join コマンドの max オプションに 0 を指定すると全ての組み合わせを網羅する形での結合(交差結合)が実現できます。
これを利用して、検索対象と検索条件の組み合わせを、1組1行で全て書き出します。

Splunk
| inputlookup "test_data.csv"
| join max=0
    [
      | inputlookup "test_search.csv"
      | eval STR_SEARCH = STR
      | fields STR_SEARCH
    ]
STR STR_SEARCH
one t*
one *e
two t*
two *e
three t*
three *e
four t*
four *e
five t*
five *e

スクリーンショット 2022-02-13 13.34.50.png

書き出した組み合わせについて、ポイントの2点目で行毎に検索を実施し、ヒットした行のみを抽出します。
2つのフィールドを比較するので、先ほどは逆に where コマンドである必要があります。
注意点として、 like 関数のワイルドカードは「任意の文字列」を表す文字が「*」でなく「%」になるので、そのように条件の文字列を変換しないとうまく動きません。

Splunk
| inputlookup "test_data.csv"
| join max=0
    [
      | inputlookup "test_search.csv"
      | eval STR_SEARCH = STR
      | eval STR_SEARCH_R = replace(STR,"\*","%")
      | fields STR_SEARCH, STR_SEARCH_R
    ]
| where like(STR, STR_SEARCH_R)
STR STR_SEARCH STR_SEARCH_R
one *e %e
two t* t%
three t* t%
three *e %e
five *e %e

スクリーンショット 2022-02-13 13.37.28.png

このようにすれば、「ヒットした値」と「ヒットした条件」の組が残るので、 stats コマンドで集計することができます。

正規表現

さらにこの方法だと、 like 関数を match 関数に変えるだけで正規表現にも対応することができます。
search コマンドで正規表現は使えないので、この方法は統計処理をしない検索だけでも有用かと思います。

Splunk
| makeresults count=200
| streamstats count AS STR
| join max=0
    [
      | makeresults count=2
      | streamstats count AS STR
      | eval STR_SEARCH = "^" + STR + "*5{1,2}$"
      | fields STR_SEARCH
    ]
| where match(STR, STR_SEARCH)
| stats count BY STR_SEARCH

スクリーンショット 2022-02-13 13.50.02.png

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?