查詢資料時使用 regex
在查詢 IBM Cloud Logs 資料時,您可以使用正規表達式(regex)進行模式搜尋和字串替換。
您可能想要從日誌中擷取特定資料,使其更容易分析及視覺化。 有時您可能想要擷取特定的記錄資料。 其他時候,您可能需要在儲存日誌之前,將敏感資料隱藏在日誌中。
您也可以使用 regex 模式而非精確的文字搜尋來進行匹配。
什麼是正規表達式?它是如何運作的?
正規表達式 (Regular Expressions) 也稱為 regex,是一種特定領域語言 (DSL),用於模式搜尋和取代。
本主題中的資訊並不打算提供完整的 regex 教育教學。 如果您不熟悉 regex,在嘗試理解此處包含的特定概念之前,您可能需要檢閱有關 regex 的公開資訊。
Regex 概念
要了解本主題中的範例,您需要知道一些基本概念。
- 擷取群組
- 括號中包含 Regex。 運算符號適用於括號內符合規格的文字。
- 命名擷取群組
- 與名稱相關聯的擷取群組。 匹配的結果可以用以下名稱參照
- 角色類別
- 方括號內 (
[]) 所括的要匹配的字元範圍。破折號可用來作為列出數個字元的速記:[1-5]與[12345]相同。
何時使用 regex
有時您不需要正則表達式,只需搜尋特定文字即可。 例如,如果您只想尋找包含文字 user logged in 的日誌行,您只需在日誌搜尋中輸入此文字即可。 但如果您的日誌行如下所示:user_32 logged in,您就無法搜尋準確的文字,因為使用者 ID 是會改變的變數。
幸運的是,有一個 regex 模式可以使用 match anything 序列來處理這種情況:
user_d+ logged in
使用 regex 將文字擷取至自訂 JSON 欄位
假設您有以下格式的非結構化日誌:
${logLevel}: World-${worldName}: ${logText}
而且,您希望將此格式的所有條目轉換成以下格式的 JSON 物件:
{
"level": `${log-level}`,
"tag": `World-${worldName}`,
"text": `${logText}`
}
您可以使用此 regex 進行轉換:
^(?P.*?):s*(?P.*?):
其中:
^是行的開始符號,表示匹配需要從行的開始開始。(?PX)其中 是要匹配的內容,並且是已命名的擷取群組語法。X這個 regex 有三個捕捉群組,每個 JSON key 需要一個。s表示「任何空白字元」。.表示「任何一個字元」。*表示「前一個符號或字元有 0 個或更多匹配項目」。.*表示「有 1 個或更多前一個符號或字元符合」。.*?表示「任何字元的任何次數,所需的代幣量最少」。
因此,regex:
^(?P.*?):s*(?P.*?):
將按以下方式處理:
-
從一行的開始到第一個
:符號的文字將被擷取為群組level。 -
在任意數量的空白符號之後,直到下一個
:符號之前的任何文字都將擷取為群組tag。 -
日誌文字會由 IBM Cloud Logs 自動設定為
text欄位,因此我們會自動擁有text欄位。
使用相同的 regex,可得到以下日誌:
"info: World-w-8: generate: new world"
被轉換成這個 JSON 物件:
{
"level": "info",
"tag": "World-w-8",
"text": "info: World-w-8: generate: new world"
}
將文字擷取至預先定義的欄位
您可能想要將文字抽取到預先定義的欄位中。 請考慮此記錄:
"info: World-w-8: generate: new world"
您可能想要將 info 文字抽取到 Severity 欄,並將 World 文字抽取到 Class 欄。
您可以修改 regex 以設定正確的擷取群組名稱,如下所示:
^(?P.*?):s*(?P.*?)-(?P.*?):
此 regex 將格式化日誌,使其顯示如圖所示。
從結構化日誌擷取特定資料
類似的方法可用於從結構化日誌中擷取資料。 以下是一個範例,說明如何從特定的 JSON 欄位擷取資料。
假設您有類似的結構化日誌行:
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
現在,如果 region 欄位的形式如下:
`rg-${"europe"|"asia"|"na"}-${number}`
我們要擷取的部分是要告訴我們這個區域是 europe, asia 或 na。 擷取資料的 regex 應該是:
"region"s*:s*"rg-(?P.*?)-
命名的擷取群組 regionName 就是擷取文字的方法。 根據我們的格式,區域名稱在關鍵名稱 region 之後,字元 rg-。 s* 符號的目的是讓 regex 在 : 符號之前或之後有任何空白的情況下仍能運作。
結果將類似於以下內容:
{
"log" : "Bye",
"regionName" : "na",
"region" : "rg-na-1",
"type" : "ltest-w-9"
}
取代和移除數值
我們需要取代或移除值的最常見例子之一就是隱藏個人資料。 假設您在某處記錄電話號碼,但不希望這些號碼儲存在 IBM Cloud Logs 中。
假設我們有這樣的非結構化日誌行:
"info: Sender: sendSms: sending sms to phone number +12345678910 to user Andrew"
您要從這一行移除電話號碼和姓名。 此 regex 將配對以 "sending sms" 開頭的一行:
sending sms to phone number +*d+ to user .*
我們需要將 + 符號轉換為空格,因為 + 在 regex 語法中有特殊意義。 此義為「1 個或更多先前的字元」。
符號 d 可匹配任何單一數字。 請記住,* 符號表示「0 或更多前一個字元」。 因此,+*d+ 會匹配一個或多個數字,這些數字可以以 + 符號作為前綴(也可以不)。
此 regex 將取代前一個 regex 匹配的文字為相同的文字,但不包含電話號碼和姓名:
sending sms to phone number * to user *
以下是應用上述規則的結果:
"info: Sender: sendSms: sending sms to phone number * to user *"
取代結構化日誌中的 JSON 值
取代結構化日誌中的 JSON 值與取代非結構化日誌中的值類似。 整個 JSON 字串會用作 Replace 規則 的輸入。
使用下列 JSON 結構:
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
假設您需要使用其他值取代 type 欄位的值。 以下是如何匹配 type 欄位的值:
"type"s*:s*".*?"
請記住,我們需要 s* 符號,以確保在 : 字元之前或之後有空白符號時,regex 可以正常運作。
以下是用 newType 取代 type 欄位中任何值的 regex:
"type":"newType"
使用反向參考
假設我們需要在格式 west-europe-2 的字串中以 eu 取代 europe。 假設我們不只需要在 region 欄位,也需要在日誌中找到字串的任何其他部分執行這項工作。 使用此 regex 即可輕鬆匹配此模式:
.+?-europe-d+
不過,使用我們之前使用的方法來取代字串可能比較困難。 這是因為我們需要在 europe 文字之前和之後插入兩個字串,而這些字串可能會有所不同。 要做到這一點,我們首先需要將字串擷取到擷取群組中:
(.+?)-europe-(d+)
請記住 d 符號的意思是「任何數字」,與 + 一起的意思是「任何數字的一次或多次」。 與此類似,.+ 表示任何符號出現一次或多次,但以最少的代幣數進行匹配。
此 regex 將擷取 europe 之前的文字為擷取群組 1,而 europe 之後的文字為擷取群組 2。 以下 regex 將使用反向參考插入這些群組的匹配內容:
$1-eu-$2
例如,應用我們的規則前的記錄:
{
"log" : "Here region is east-europe-1. That's it",
"type" : "newType",
"region" : "east-europe-1"
}
以及套用規則後的記錄:
{
"log" : "Here region is east-eu-1. That's it",
"type" : "newType",
"region" : "east-eu-1"
}
從日誌搜尋列使用 regex 搜尋
另一個可以使用 regex 的地方是 IBM Cloud Logs UI 日誌頁面的搜尋列。
從頁面搜尋列搜尋時,您可以輸入精確文字、Lucene 或 Dataprime 查詢。 您也可以使用 regex 來尋找特定的模式。 Regex 查詢有其自己的格式,即:
/${fieldName}.keyword:/REGEX//
假設我們有許多格式如下的 JSON 結構日誌:
{
"log": `${text}` ,
"regionName": `${text}`,
"region": `${text}`,
"type" : `ltest-w-${number}`
}
我們只想匹配 type 等於 ltest-w-1, ltest-w-2 或 ltest-w-3 的項目。 以下的搜尋查詢可以達到此目的:
/type.keyword:/ltest-w-[1-3]//
[ 和 ],方括號之間的文字稱為字元類。 它匹配方括號之間列出的任何一個字符。 破折號可作為列出數個字元的速記:[1-5] 與 [12345] 相同。
您可以使用相同的語法,以 regex 來匹配未經刪除記錄中的資料。 您只需將欄位名稱設定為 text.keyword。 例如:
/text.keyword:/.*ltest-w-[1-3].*//
此 regex 將會搜尋主記錄正文中的文字 ltest-w-1, ltest-w-2 或 ltest-w-3。
使用 regex 觸發警示
IBM Cloud Logs 中 regex 的另一個常用情況是定義警報。警報語法與日誌查詢語法相同。
比方說,我們希望在以下形式的行中提醒我們:
`App: init: World-${name}: generation error: ${err}`
假設我們只想取得世界 w-1, w-2, w-3 或 w-4 的警示。 我們的警示重組將如下所示:
/text.keyword:/.*World-w-[1-4]: generation error.*//
請記住,[1-4] 會匹配從 1 到 4 的任何單一字元,而 .* 會匹配任何字元的任何次數。
有關警示的更多資訊,請參閱: