Extraire des données à partir de champs de chaîne non structurés

Effectué

Les données du journal de sécurité sont souvent contenues dans des champs de chaîne non structurés et nécessitent une analyse pour extraire des données. Il existe plusieurs façons d’extraire des informations à partir de champs de chaîne avec le KQL. Les deux opérateurs principaux utilisés sont « extract » et « parse ».

extract

« Extract » obtient une correspondance pour une expression régulière à partir d’une chaîne de texte. Vous pouvez éventuellement convertir la sous-chaîne extraite en type indiqué.

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

Arguments

  • regex : Expression régulière.

  • captureGroup : constante positive identifiant le groupe de capture à extraire. Les valeurs sont 0 pour la correspondance entière, 1 pour la valeur mise en correspondance par la première '('parenthèse')' dans l’expression régulière, 2 ou plus pour les parenthèses suivantes.

  • text : chaîne à rechercher.

  • typeLiteral : littéral de type facultatif (par exemple, typeof(long)). Si elle est fournie, la sous-chaîne extraite est convertie dans ce type.

Retours

Si regex trouve une correspondance dans text : sous-chaîne correspondant au captureGroup indiqué, éventuellement convertie en typeLiteral.

S’il n’y a aucune correspondance ou si la conversion de type échoue : null.

L’exemple suivant utilise la fonction « extract » pour extraire le nom du compte du champ « Account » de la table « SecurityEvent ».

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 évalue une expression de chaîne et analyse sa valeur en une ou plusieurs colonnes calculées. Les colonnes calculées contiendront des valeurs « null » pour les chaînes dont l’analyse a échoué.

Syntaxe

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

Arguments

  • T : table d’entrée.

  • kind :

    • simple (valeur par défaut) : StringConstant est une valeur de chaîne normale et la correspondance est stricte. Tous les délimiteurs de chaîne doivent apparaître dans la chaîne analysée, et toutes les colonnes étendues doivent correspondre aux types requis.

    • regex : StringConstant peut être une expression régulière et la correspondance est stricte. Tous les délimiteurs de chaîne, qui peuvent être une expression régulière pour ce mode, doivent apparaître dans la chaîne analysée, et toutes les colonnes étendues doivent correspondre aux types requis.

    • flags : indicateurs à utiliser en mode expression régulière comme U (non gourmand), m (mode multiligne), s (mettre en correspondance nouvelle ligne \n) et i (non-respect de la casse) dans les indicateurs RE2.

    • relaxed : StringConstant est une valeur de chaîne normale et la correspondance est approximative. Tous les délimiteurs de chaîne doivent apparaître dans la chaîne analysée, mais les colonnes étendues peuvent correspondre partiellement aux types requis. Les colonnes étendues qui ne correspondent pas aux types requis obtiendront la valeur null.

  • Expression : expression qui prend la valeur d’une chaîne.

  • ColumnName : nom d’une colonne à laquelle attribuer une valeur extraite de l’expression de chaîne.

  • ColumnType : facultatif. Valeur scalaire indiquant le type vers lequel convertir la valeur. La valeur par défaut est le type de chaîne.

Retours

Table d’entrée, étendue conformément à la liste des colonnes fournies à l’opérateur.

L’instruction suivante illustre l’opérateur parse, qui évalue une expression de chaîne et analyse sa valeur en une ou plusieurs colonnes calculées. À utiliser pour structurer des données non structurées.

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