非構造化文字列フィールドからデータを抽出する

完了

セキュリティ ログ データは、多くの場合、非構造化文字列フィールドに含まれており、データを抽出するための解析が必要です。 KQL の文字列フィールドから情報をプルする方法は複数あります。 使用される 2 つの主な演算子は、extract と parse です。

extract

extract では、テキスト文字列から正規表現との一致を抽出します。 必要に応じて、抽出されたサブ文字列を指定された型に変換することもできます。

print extract("x=([0-9.]+)", 1, "hello x=45.6|wo") == "45.6"

引数

  • regex: 正規表現。

  • captureGroup: 抽出するキャプチャ グループを示す正の int 定数。 "0" は一致全体、"1" は正規表現の最初のかっこで囲まれた部分と一致した値、2 以上は後続のかっこを示します。

  • text: 検索対象の文字列。

  • typeLiteral: 省略可能な type リテラル (例: typeof(long))。 指定した場合、抽出された部分文字列はこの型に変換されます。

戻り値

regex が text 内で一致を見つけた場合: 指定されたキャプチャ グループ captureGroup に対応する部分文字列。オプションで、typeLiteral に変換できます。

一致がないか、型変換が失敗した場合は、null です。

次の例では、extract 関数を使用して、SecurityEvent テーブルの Account フィールドから Account Name を取得します。

SecurityEvent
| where EventID == 4672 and AccountType == 'User'
| extend Account_Name = extract(@"^(.*\\)?([^@]*)(@.*)?$", 2, tolower(Account))
| summarize LoginCount = count() by Account_Name
| where Account_Name != ""
| where LoginCount < 10

parse

parse を使用すると文字列式が評価され、その値が 1 つまたは複数の計算列に解析されます。 解析に失敗した文字列の計算列には null が含まれます。

構文

T | parse [kind=regex [flags=regex_flags] |simple|relaxed] Expression with * (StringConstant ColumnName [: ColumnType]) *

引数

  • T: 入力テーブル。

  • kind:

    • simple (既定値):StringConstant は通常の文字列値であり、一致は厳密です。 すべての文字列の区切り記号が解析される文字列に含まれ、すべての拡張列が必要な型と一致している必要があります。

    • regex:StringConstant は正規表現が可能であり、一致は厳密です。 すべての文字列の区切り記号 (このモードでは正規表現が可能です) が解析される文字列に含まれ、すべての拡張列が必要な型と一致している必要があります。

    • flags: RE2 フラグの U (Ungreedy)、m (複数行モード)、s (改行 \n と一致)、i (大文字と小文字の区別なし) などの正規表現モードで使用されるフラグ。

    • relaxed:StringConstant は通常の文字列値であり、一致は緩やかです。 すべての文字列の区切り記号が解析される文字列に含まれている必要がありますが、拡張列では必要な型との部分的な一致が可能です。 必要な型と一致しなかった拡張列には値 null が返ります。

  • Expression: 文字列に対して評価される式。

  • ColumnName: 文字列式から抽出された値を代入する列の名前。

  • ColumnType: 省略可能。 値の変換後の型を示すスカラー値。 既定値は文字列型です。

戻り値

演算子に指定された列の一覧に従って拡張された入力テーブル。

次のステートメントは、文字列式を評価して、その値を 1 つ以上の計算列に解析する parse 演算子を示しています。 非構造化データを構造化するために使用されます。

let Traces = datatable(EventText:string)
[
"Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=23, lockTime=02/17/2016 08:40:01, releaseTime=02/17/2016 08:40:01, previousLockTime=02/17/2016 08:39:01)",
"Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=15, lockTime=02/17/2016 08:40:00, releaseTime=02/17/2016 08:40:00, previousLockTime=02/17/2016 08:39:00)",
"Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=20, lockTime=02/17/2016 08:40:01, releaseTime=02/17/2016 08:40:01, previousLockTime=02/17/2016 08:39:01)",
"Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=22, lockTime=02/17/2016 08:41:01, releaseTime=02/17/2016 08:41:00, previousLockTime=02/17/2016 08:40:01)",
"Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=16, lockTime=02/17/2016 08:41:00, releaseTime=02/17/2016 08:41:00, previousLockTime=02/17/2016 08:40:00)"
];
Traces  
| parse EventText with * "resourceName=" resourceName ", totalSlices=" totalSlices:long * "sliceNumber=" sliceNumber:long * "lockTime=" lockTime ", releaseTime=" releaseTime:date "," * "previousLockTime=" previousLockTime:date ")" *  
| project resourceName, totalSlices, sliceNumber, lockTime, releaseTime, previousLockTime