在 Azure Monitor 日志查询中使用字符串Work with strings in Azure Monitor log queries

备注

完成本教程之前,应先完成 Azure Monitor 日志分析入门Azure Monitor 日志查询入门You should complete Get started with Azure Monitor log analytics and Getting started with Azure Monitor log queries before completing this tutorial.

备注

可以在自己的 Log Analytics 环境中完成此练习,也可以使用我们的演示环境,其中包含大量样本数据。You can work through this exercise in your own Log Analytics environment, or you can use our Demo environment, which includes plenty of sample data.

本文介绍如何编辑、比较、搜索字符串以及对其执行其他各种操作。This article describes how to edit, compare, search in and perform a variety of other operations on strings.

字符串中的每个字符都有一个与其位置相符的索引号。Each character in a string has an index number, according to its location. 第一个字符位于索引 0 处,下一个字符位于索引 1 处,依此类推。The first character is at index 0, the next character is 1, and so one. 不同的字符串函数使用以下各部分所示的索引号。Different string functions use index numbers as shown in the following sections. 下面的许多示例使用 print 命令来演示在不使用特定数据源的情况下如何处理字符串。Many of the following examples use the print command for to demonstrate string manipulation without using a specific data source.

字符串及其转义Strings and escaping them

字符串值包装在单引号或双引号字符中。String values are wrapped with either with single or double quote characters. 反斜杠 () 用于将字符转义为其后面的字符,例如,\t 表示 tab(制表符),\n 表示 newline(换行符)," 表示引号字符本身。Backslash () is used to escape characters to the character following it, such as \t for tab, \n for newline, and " the quote character itself.

print "this is a 'string' literal in double \" quotes"
print 'this is a "string" literal in single \' quotes'

为了防止“\”用作转义字符,请添加“@”作为字符串的前缀:To prevent "\" from acting as an escape character, add "@" as a prefix to the string:

print @"C:\backslash\not\escaped\with @ prefix"

字符串比较String comparisons

运算符Operator 说明Description 区分大小写Case-Sensitive 示例(生成 trueExample (yields true)
== 等于Equals Yes "aBc" == "aBc"
!= 不等于Not equals Yes "abc" != "ABC"
=~ 等于Equals No "abc" =~ "ABC"
!~ 不等于Not equals No "aBc" !~ "xyz"
has 右侧是左侧的整个字词Right-hand-side is a whole term in left-hand-side No "North America" has "america"
!has 右侧不是左侧的完整字词Right-hand-side isn't a full term in left-hand-side No "North America" !has "amer"
has_cs 右侧是左侧的整个字词Right-hand-side is a whole term in left-hand-side Yes "North America" has_cs "America"
!has_cs 右侧不是左侧的完整字词Right-hand-side isn't a full term in left-hand-side Yes "North America" !has_cs "amer"
hasprefix 右侧是左侧的字词前缀Right-hand-side is a term prefix in left-hand-side No "North America" hasprefix "ame"
!hasprefix 右侧不是左侧的字词前缀Right-hand-side isn't a term prefix in left-hand-side No "North America" !hasprefix "mer"
hasprefix_cs 右侧是左侧的字词前缀Right-hand-side is a term prefix in left-hand-side Yes "North America" hasprefix_cs "Ame"
!hasprefix_cs 右侧不是左侧的字词前缀Right-hand-side isn't a term prefix in left-hand-side Yes "North America" !hasprefix_cs "CA"
hassuffix 右侧是左侧的字词后缀Right-hand-side is a term suffix in left-hand-side No "North America" hassuffix "ica"
!hassuffix 右侧不是左侧的字词后缀Right-hand-side isn't a term suffix in left-hand-side No "North America" !hassuffix "americ"
hassuffix_cs 右侧是左侧的字词后缀Right-hand-side is a term suffix in left-hand-side Yes "North America" hassuffix_cs "ica"
!hassuffix_cs 右侧不是左侧的字词后缀Right-hand-side isn't a term suffix in left-hand-side Yes "North America" !hassuffix_cs "icA"
contains 右侧作为左侧的子序列出现Right-hand-side occurs as a subsequence of left-hand-side No "FabriKam" contains "BRik"
!contains 右侧不会在左侧出现Right-hand-side doesn't occur in left-hand-side No "Fabrikam" !contains "xyz"
contains_cs 右侧作为左侧的子序列出现Right-hand-side occurs as a subsequence of left-hand-side Yes "FabriKam" contains_cs "Kam"
!contains_cs 右侧不会在左侧出现Right-hand-side doesn't occur in left-hand-side Yes "Fabrikam" !contains_cs "Kam"
startswith 右侧是左侧的初始子序列Right-hand-side is an initial subsequence of left-hand-side No "Fabrikam" startswith "fab"
!startswith 右侧不是左侧的初始子序列Right-hand-side isn't an initial subsequence of left-hand-side No "Fabrikam" !startswith "kam"
startswith_cs 右侧是左侧的初始子序列Right-hand-side is an initial subsequence of left-hand-side Yes "Fabrikam" startswith_cs "Fab"
!startswith_cs 右侧不是左侧的初始子序列Right-hand-side isn't an initial subsequence of left-hand-side Yes "Fabrikam" !startswith_cs "fab"
endswith 右侧是左侧的结束子序列Right-hand-side is a closing subsequence of left-hand-side No "Fabrikam" endswith "Kam"
!endswith 右侧不是左侧的结束子序列Right-hand-side isn't a closing subsequence of left-hand-side No "Fabrikam" !endswith "brik"
endswith_cs 右侧是左侧的结束子序列Right-hand-side is a closing subsequence of left-hand-side Yes "Fabrikam" endswith "Kam"
!endswith_cs 右侧不是左侧的结束子序列Right-hand-side isn't a closing subsequence of left-hand-side Yes "Fabrikam" !endswith "brik"
matches regex 左侧包含右侧的匹配项left-hand-side contains a match for Right-hand-side Yes "Fabrikam" matches regex "b.*k"
in 等于某个元素Equals to one of the elements Yes "abc" in ("123", "345", "abc")
!in 不等于任何元素Not equals to any of the elements Yes "bca" !in ("123", "345", "abc")

countofcountof

计算字符串中子字符串的出现次数。Counts occurrences of a substring in a string. 可以匹配纯字符串或使用正则表达式。Can match plain strings or use regex. 纯字符串匹配项可能重叠,而正则表达式匹配项则不会。Plain string matches may overlap while regex matches don't.

语法Syntax

countof(text, search [, kind])

参数:Arguments:

  • text - 输入字符串text - The input string
  • search - 用于在文本内部匹配的纯字符串或正则表达式。search - Plain string or regular expression to match inside text.
  • kind - normal | regex(默认值:normal)。kind - normal | regex (default: normal).

返回值Returns

搜索字符串可在容器中匹配的次数。The number of times that the search string can be matched in the container. 纯字符串匹配项可能重叠,而正则表达式匹配项则不会。Plain string matches may overlap while regex matches do not.

示例Examples

纯字符串匹配项Plain string matches

print countof("The cat sat on the mat", "at");  //result: 3
print countof("aaa", "a");  //result: 3
print countof("aaaa", "aa");  //result: 3 (not 2!)
print countof("ababa", "ab", "normal");  //result: 2
print countof("ababa", "aba");  //result: 2

正则表达式匹配项Regex matches

print countof("The cat sat on the mat", @"\b.at\b", "regex");  //result: 3
print countof("ababa", "aba", "regex");  //result: 1
print countof("abcabc", "a.c", "regex");  // result: 2

extractextract

从给定的字符串中获取正则表达式的匹配项。Gets a match for a regular expression from a given string. (可选)还可将提取的子字符串转换为指定的类型。Optionally also converts the extracted substring the specified type.

语法Syntax

extract(regex, captureGroup, text [, typeLiteral])

参数Arguments

  • regex - 正则表达式。regex - A regular expression.
  • captureGroup - 指示待提取的捕获组的正整数常量。captureGroup - A positive integer constant indicating the capture group to extract. 0 代表整个匹配项,1 代表正则表达式中第一个“(括号)”匹配的值,2 及以上数字代表后续括号。0 for the entire match, 1 for the value matched by the first '('parenthesis')' in the regular expression, 2 or more for subsequent parentheses.
  • text - 要搜索的字符串。text - A string to search.
  • typeLiteral - 可选的类型文本(例如 typeof(long))。typeLiteral - An optional type literal (for example, typeof(long)). (如果支持)提取的子字符串将转换成此类型。If provided, the extracted substring is converted to this type.

返回值Returns

与指定捕获组 captureGroup 匹配的子字符串可转换为 typeLiteral(可选)。The substring matched against the indicated capture group captureGroup, optionally converted to typeLiteral. 如果没有匹配项或类型转换失败,则返回 null。If there's no match, or the type conversion fails, return null.

示例Examples

以下示例从检测信号记录中提取 ComputerIP 的最后一个八位字节:The following example extracts the last octet of ComputerIP from a heartbeat record:

Heartbeat
| where ComputerIP != "" 
| take 1
| project ComputerIP, last_octet=extract("([0-9]*$)", 1, ComputerIP) 

以下示例提取最后一个八位字节,将其强制转换为 real 类型(数字),并计算下一个 IP 值The following example extracts the last octet, casts it to a real type (number) and calculates the next IP value

Heartbeat
| where ComputerIP != "" 
| take 1
| extend last_octet=extract("([0-9]*$)", 1, ComputerIP, typeof(real)) 
| extend next_ip=(last_octet+1)%255
| project ComputerIP, last_octet, next_ip

以下示例在字符串 Trace 中搜索“Duration”的定义。In the example below, the string Trace is searched for a definition of "Duration". 匹配项强制转换为 real 并与时间常量 (1 s) 相乘,该常量将 Duration 强制转换为 timespan 类型。The match is cast to real and multiplied by a time constant (1 s) which casts Duration to type timespan.

let Trace="A=12, B=34, Duration=567, ...";
print Duration = extract("Duration=([0-9.]+)", 1, Trace, typeof(real));  //result: 567
print Duration_seconds =  extract("Duration=([0-9.]+)", 1, Trace, typeof(real)) * time(1s);  //result: 00:09:27

isempty, isnotempty, notemptyisempty, isnotempty, notempty

  • 如果参数是空字符串或 null,则 isempty 返回 true(另请参阅 isnull)。isempty returns true if the argument is an empty string or null (see also isnull).
  • 如果参数不是空字符串或 null,则 isnotempty 返回 true(另请参阅 isnotnull)。isnotempty returns true if the argument isn't an empty string or a null (see also isnotnull). 别名:notemptyalias: notempty.

语法Syntax

isempty(value)
isnotempty(value)

示例Examples

print isempty("");  // result: true

print isempty("0");  // result: false

print isempty(0);  // result: false

print isempty(5);  // result: false

Heartbeat | where isnotempty(ComputerIP) | take 1  // return 1 Heartbeat record in which ComputerIP isn't empty

parseurlparseurl

将 URL 拆分为不同的组成部分(protocol、host、port 等),并返回包含字符串形式的组成部分的字典对象。Splits a URL into its parts (protocol, host, port, etc.), and returns a dictionary object containing the parts as strings.

语法Syntax

parseurl(urlstring)

示例Examples

print parseurl("http://user:pass@contoso.com/icecream/buy.aspx?a=1&b=2#tag")

结果将是:The outcome will be:

{
    "Scheme" : "http",
    "Host" : "contoso.com",
    "Port" : "80",
    "Path" : "/icecream/buy.aspx",
    "Username" : "user",
    "Password" : "pass",
    "Query Parameters" : {"a":"1","b":"2"},
    "Fragment" : "tag"
}

replacereplace

将所有正则表达式匹配项替换为另一字符串。Replaces all regex matches with another string.

语法Syntax

replace(regex, rewrite, input_text)

参数Arguments

  • regex - 作为匹配依据的正则表达式。regex - The regular expression to match by. 可在“(括号)”中包含捕获组。It can contain capture groups in '('parentheses')'.
  • rewrite - 由匹配正则表达式匹配的任何匹配项的替换正则表达式。rewrite - The replacement regex for any match made by matching regex. 使用 \0 引用整个匹配项,使用 \1 引用第一个捕获组,使用 \2 等引用后续捕获组。Use \0 to refer to the whole match, \1 for the first capture group, \2, and so on for subsequent capture groups.
  • input_text - 要在其中搜索的输入字符串。input_text - The input string to search in.

返回值Returns

使用 rewrite 计算结果替换正则表达式的所有匹配项后面的文本。The text after replacing all matches of regex with evaluations of rewrite. 匹配项不会重叠。Matches don't overlap.

示例Examples

SecurityEvent
| take 1
| project Activity 
| extend replaced = replace(@"(\d+) -", @"Activity ID \1: ", Activity) 

可能返回以下结果:Can have the following results:

活动Activity 替换的内容replaced
4663 - 尝试访问某个对象4663 - An attempt was made to access an object 活动 ID 4663:尝试访问某个对象。Activity ID 4663: An attempt was made to access an object.

splitsplit

根据指定的分隔符拆分给定的字符串,并返回生成的子字符串的数组。Splits a given string according to a specified delimiter, and returns an array of the resulting substrings.

语法Syntax

split(source, delimiter [, requestedIndex])

参数:Arguments:

  • source - 要根据指定的分隔符拆分的字符串。source - The string to be split according to the specified delimiter.
  • delimiter - 用于拆分源字符串的分隔符。delimiter - The delimiter that will be used in order to split the source string.
  • requestedIndex - 可选的从零开始的索引。requestedIndex - An optional zero-based index. 如果已提供,则返回的字符串数组只包含该项(如果存在)。If provided, the returned string array will hold only that item (if exists).

示例Examples

print split("aaa_bbb_ccc", "_");    // result: ["aaa","bbb","ccc"]
print split("aa_bb", "_");          // result: ["aa","bb"]
print split("aaa_bbb_ccc", "_", 1); // result: ["bbb"]
print split("", "_");               // result: [""]
print split("a__b", "_");           // result: ["a","","b"]
print split("aabbcc", "bb");        // result: ["aa","cc"]

strcatstrcat

连接字符串参数(支持 1-16 个参数)。Concatenates string arguments (supports 1-16 arguments).

语法Syntax

strcat("string1", "string2", "string3")

示例Examples

print strcat("hello", " ", "world") // result: "hello world"

strlenstrlen

返回字符串的长度。Returns the length of a string.

语法Syntax

strlen("text_to_evaluate")

示例Examples

print strlen("hello")   // result: 5

substringsubstring

从给定的源字符串提取某个子字符串(从指定的索引开始)。Extracts a substring from a given source string, starting at the specified index. (可选)可以指定请求子字符串的长度。Optionally, the length of the requested substring can be specified.

语法Syntax

substring(source, startingIndex [, length])

参数:Arguments:

  • source - 从中提取子字符串的源字符串。source - The source string that the substring will be taken from.
  • startingIndex - 请求子字符串的从零开始的起始字符位置。startingIndex - The zero-based starting character position of the requested substring.
  • length - 可选的参数,可用于指定返回的子字符串的请求长度。length - An optional parameter that can be used to specify the requested length of the returned substring.

示例Examples

print substring("abcdefg", 1, 2);   // result: "bc"
print substring("123456", 1);       // result: "23456"
print substring("123456", 2, 2);    // result: "34"
print substring("ABCD", 0, 2);  // result: "AB"

tolower、touppertolower, toupper

将给定的字符串转换为全小写或全大写。Converts a given string to all lower or upper case.

语法Syntax

tolower("value")
toupper("value")

示例Examples

print tolower("HELLO"); // result: "hello"
print toupper("hello"); // result: "HELLO"

后续步骤Next steps

继续学习高级教程:Continue with the advanced tutorials: