
Microsoft Sentinel KQL क्वेरी और ट्यूटोरियल का चयनित संग्रह — खतरों की खोज, Azure AD साइन-इन लॉग का विश्लेषण, विसंगतियों का पता लगाने और कुशल डिटेक्शन पैटर्न बनाने के लिए।
Microsoft Sentinel के लिए KQL का उपयोग करने के लिए कुछ टिप्स, ट्रिक्स और उदाहरण।
Kusto Query Language वह भाषा है जिसका उपयोग Azure Monitor, Azure Data Explorer और Azure Log Analytics में किया जाता है (Microsoft Sentinel अंदरूनी रूप से यही उपयोग करता है)। मुझे KQL के संबंध में यह विज़ुअलाइज़ेशन हमेशा उपयोगी लगा है -

हम KQL का उपयोग करके अपने बड़े डेटा सेट के भीतर से खतरों, डिटेक्शन, पैटर्न और विसंगतियों को खोजने के लिए सटीक और कुशल क्वेरी बनाना चाहते हैं।
नीचे दी गई क्वेरी को एक उदाहरण के रूप में लें```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent
जब हम इस तरह की क्वेरी चलाते हैं, तो पहली पंक्ति Microsoft Sentinel को बताती है कि डेटा के लिए किस तालिका में देखना है, इसलिए इस मामले में हम SigninLogs तालिका खोजना चाहते हैं, जहाँ Azure AD साइन-इन डेटा भेजा जाता है। आप तालिकाओं की सूची [यहाँ](https://docs.microsoft.com/en-us/azure/sentinel/data-source-schema-reference) देख सकते हैं।
Microsoft Sentinel फिर आपकी क्वेरी को क्रमिक रूप से चलाएगा, इसलिए वह प्रत्येक पंक्ति को एक-एक करके तब तक चलाएगा जब तक वह अंत तक नहीं पहुँच जाता, या आपको कोई त्रुटि नहीं होती। तो आइए अपनी क्वेरी को पंक्ति दर पंक्ति तोड़ें।```kql
SigninLogs
तो सबसे पहले हमने अपनी SigninLogs तालिका चुनी है।```kql SigninLogs | where TimeGenerated > ago(14d)
इसके बाद हम Sentinel को इस तालिका में पिछले 14 दिनों के डेटा को देखने के लिए कहते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
आगे हम Sentinel से केवल उन लॉग्स को खोजने के लिए कहते हैं जहाँ UserPrincipalName "[email protected]" के बराबर है```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0"
फिर हम केवल उन लॉग्स को देखते हैं जहाँ ResultType == 0 है, जो Azure AD में एक सफल लॉगऑन है।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| where AppDisplayName == "Microsoft Teams"
अगला, हम केवल Microsoft Teams में साइन-इन की तलाश करते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent
हमारी अंतिम पंक्ति project ऑपरेटर का उपयोग करती है, ताकि हमारे लॉग्स से केवल 4 फ़ील्ड्स लौटाए जाएँ, इसलिए हम केवल TimeGenerated, Location, IPAddress और UserAgent ही देख पाएँगे जो हमारे SigninLogs डेटा से लौटाए गए हैं।
इस तरह आप क्वेरी बनाते हैं, अब मूल बातें।
## मूल बातें
### समय की मूल बातें
Microsoft Sentinel और KQL समय फ़िल्टर के लिए अत्यधिक अनुकूलित हैं, इसलिए यदि आप उस डेटा की समय अवधि जानते हैं जिसे आप खोजना चाहते हैं, तो आपको तुरंत समय सीमा फ़िल्टर कर देनी चाहिए। पिछले 14 दिनों के लॉग्स प्राप्त करना, फिर नीचे दी गई क्वेरी जैसे उपयोगकर्ता नाम की खोज करना -```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
पहले उपयोगकर्ता नाम और फिर समय अवधि खोजने की तुलना में कहीं अधिक कुशल है, जैसे -```kql SigninLogs | where UserPrincipalName == "[email protected]" | where TimeGenerated > ago(14d)
KQL के पास विशिष्ट समय अवधियों की क्वेरी करने के लिए कई विकल्प हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
पहले उदाहरण के अनुसार, यह पिछले 14 दिनों की खोज करेगा।```kql SigninLogs | where TimeGenerated > ago(14h)
आप घंटे भी कर सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14m)
और मिनट।
KQL समय सीमा के बीच क्वेरी करने का भी समर्थन करता है -```kql SigninLogs | where TimeGenerated between (ago(14d) .. ago(7d))
यह 14 दिन पहले और 7 दिन पहले के बीच का SigninLogs डेटा खोजेगा।```kql
SigninLogs
| where TimeGenerated between (ago(14h) .. ago(7h))
14 घंटे और 7 घंटे पहले के बीच।```kql SigninLogs | where TimeGenerated between (ago(14m) .. ago(7m))
और 14 मिनट पहले से 7 मिनट पहले के बीच।
### Where मूल बातें
Where एक ऑपरेटर है जिसका उपयोग आप अपने द्वारा लिखे जाने वाले लगभग हर क्वेरी में करेंगे। इसी तरह आप Microsoft Sentinel को विशिष्ट डेटा खोजने के लिए कहते हैं। where ऑपरेटर के साथ सिंटैक्स बहुत महत्वपूर्ण है। अगर हम अपना वही उदाहरण उपयोग करते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
यह पिछले 14 दिनों में हमारी SigninLogs तालिका में सटीक मिलानों की खोज करेगा, जहाँ हमारा UserPrincipalName [email protected] के बराबर है। KQL में == केस-सेंसिटिव है, इसलिए यदि आप [email protected] के लिए खोज करते हैं और उपयोगकर्ता नाम वास्तव में [email protected] है, तो आपको कोई परिणाम नहीं मिलेगा। गैर-केस-सेंसिटिव समकक्ष =~ है।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName =~ "[email protected]"
यह केस संवेदनशीलता की परवाह किए बिना [email protected] के लिए कोई भी मिलान खोजेगा।
बराबर के बजाय, हम contains का भी उपयोग कर सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName contains "reprise_99"
यह उन सभी लॉग प्रविष्टियों को ढूंढेगा जहां UserPrincipalName में reprise_99 शामिल है, यदि आपके पास [email protected] और [email protected] डेटा है, तो यह दोनों को ढूंढ लेगा। contains ऑपरेटर केस-सेंसिटिव नहीं है, लेकिन आप इसे केस-सेंसिटिव बनाने के लिए contains_cs का उपयोग कर सकते हैं।
यदि आप विशेष पैटर्न खोज रहे हैं तो आप startswith या endswith का उपयोग कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName startswith "reprise_99"
SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName endswith "testdomain.com"
startswith और endswith दोनों केस-सेंसिटिव नहीं हैं, लेकिन आप उन्हें केस-सेंसिटिव बनाने के लिए startswith_cs या endswith_cs का उपयोग कर सकते हैं।
यदि आप पूर्ण शब्दों (चार वर्णों से अधिक) की खोज कर रहे हैं, तो KQL में आप has ऑपरेटर का उपयोग कर सकते हैं। 'has' का उपयोग 'contains' की तुलना में अधिक कुशल है क्योंकि डेटा आपके लिए अनुक्रमित होता है।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName has "Teams"
यह किसी भी SigninLogs को खोजेगा जहाँ एप्लिकेशन डिस्प्ले नाम में Teams शब्द हो, जिसमें "Microsoft Teams" और "Microsoft Teams Web Client" शामिल हो सकते हैं, दोनों क्वेरी को संतुष्ट करते हैं।
यदि आप कई शब्दों की खोज कर रहे हैं तो आप has_any या has_all का उपयोग कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where AppDisplayName has_any ("Teams","Outlook")
यह उन परिणामों को लौटाएगा जहाँ एप्लिकेशन प्रदर्शन नाम में "Teams" या "Outlook" शामिल है```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName has_all ("Teams","Outlook")
यह उन परिणामों को लौटाएगा जहाँ एप्लिकेशन के डिस्प्ले नाम में "Teams" और "Outlook" शामिल हैं।
यदि आप नहीं जानते कि किन फ़ील्ड्स में खोजना है, तो आप वाइल्डकार्ड का भी उपयोग कर सकते हैं। यह अक्षम है, लेकिन यह आपको वह खोजने के लिए सही रास्ते पर ले जा सकता है जो आप चाहते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where * contains "reprise_99"
यह SigninLogs तालिका में किसी भी ऐसे फ़ील्ड की खोज करेगा जिसमें reprise_99 हो।
इनमें से कई विकल्प क्वेरी को उलटने और उन परिणामों को खोजने के लिए ! का उपयोग करने का समर्थन भी करते हैं जहाँ यह सत्य नहीं है।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName != "[email protected]"
यह क्वेरी उन सभी SigninLogs को ढूंढेगी जहाँ UserPrincipalName, [email protected] के बराबर नहीं है।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName !contains "reprise_99"
यह क्वेरी उन सभी SigninLogs को ढूंढेगी जहाँ UserPrincipalName में reprise_99 शामिल नहीं है```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName !has "Teams"
यह क्वेरी उन SigninLogs को खोजेगी जहाँ एप्लिकेशन display name में "Teams" नहीं होता।
Project हमें यह चुनने की सुविधा देता है कि हमारी क्वेरी में कौन से columns लौटाए जाएँ और किस क्रम में।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent
यह क्वेरी पिछले 14 दिनों से SigninLogs डेटा खोजती है, जहाँ UserPrincipalname [email protected] के बराबर है, जहाँ ResultType 0 है, जहाँ एप्लिकेशन display name "Microsoft Teams" के बराबर है, फिर उस क्वेरी पर प्रत्येक मिलान के लिए यह TimeGenerated, Location, IPAddress और UserAgent लौटाता है।
हम उसी फ़ंक्शन के भाग के रूप में कॉलम का नाम बदल सकते हैं।```kql
| project LogTime=TimeGenerated, SigninLocation=Location, IP=IPAddress, Agent=UserAgent
यह समान डेटा लौटाता है, लेकिन कॉलमों का नाम बदलकर LogTime, SigninLocation, IP और Agent कर देता है। हम project operator के साथ आउटपुट को इनलाइन भी संशोधित कर सकते हैं।```kql | project LocalTime=TimeGenerated+5h, Location, IPAddress, UserAgent
This returns the same data, but changes the TimeGenerated name to LocalTime and converts to a +5h time zone if you work in that time zone.
project-away is the opposite of project and will remove columns from your query.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| project-away UserAgent
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| where AppDisplayName == "Microsoft Teams"
इस क्वेरी में हम UserAgent को हटाते हैं। याद रखें, यदि आप किसी कॉलम को हटाते हैं तो आप बाद में अपनी क्वेरी में उस तक नहीं पहुँच सकते।
Summarize आपकी क्वेरी की सामग्री को एकत्रित करने वाली एक तालिका तैयार करता है। Summarize के अंतर्निहित कई समुच्चयन (aggregation) फ़ंक्शन होते हैं। यदि हम फिर से अपनी उदाहरण क्वेरी लें, तो हम summarize का उपयोग करके परिणामों को विभिन्न तरीकों से बदल सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize count() by AppDisplayName
यह क्वेरी पिछले 14 दिनों में SigninLogs तालिका में किसी भी ईवेंट को खोजेगी, [email protected] के किसी भी मिलान के लिए, जहाँ परिणाम सफल है (ResultType == 0) और फिर उन ईवेंट्स को एप्लिकेशन डिस्प्ले नाम द्वारा सारांशित करेगी।
आप वैकल्पिक रूप से परिणाम कॉलम को नाम दे सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppCount=count() by AppDisplayName
यह समान डेटा लौटाता है लेकिन लौटाए गए कॉलम का नाम अपडेट करके AppCount कर देता है।
कुल गणना के बजाय, आप एक distinct गणना का सारांश भी प्रस्तुत कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize DistinctAppCount=dcount(AppDisplayName) by AppDisplayName
This will return a single record for each distinct application [email protected] signed into.
You can use the arg_max and arg_min functions to return either the newest or oldest record that matches your query.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize arg_max(TimeGenerated, *) by UserPrincipalName
यह क्वेरी पिछले 14 दिनों के सभी साइन-इन लॉग को खोजती है, जिनमें UserPrincipalname के रूप में [email protected] है, जो सफल हैं और फिर नवीनतम रिकॉर्ड लौटाती है।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize arg_min(TimeGenerated, *) by UserPrincipalName
यह समान है लेकिन सबसे पुराना रिकॉर्ड लौटाता है।
आप अपने योगों को तर्क प्रदान करने के लिए countif का उपयोग कर सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize TeamsLogons=countif(AppDisplayName has "Teams"), SharePointLogons=countif(AppDisplayName has "SharePoint")
यह डेटा को दो नए कॉलमों में सारांशित करता है, TeamsLogons जहाँ एप्लिकेशन डिस्प्ले नाम में "Teams" होता है और SharePointLogons जहाँ एप्लिकेशन डिस्प्ले नाम में "SharePoint" होता है।
आप KQL को अपने डेटा को time 'bins' में रखने के लिए कहकर अपने डेटा को और अधिक हेरफेर कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count() by AppDisplayName, bin(TimeGenerated, 1d)
यह हमारे पहले summarize उदाहरण के समान डेटा लौटाता है और फिर उस डेटा को 1d bins में समूहित करता है।
आप इन फ़ंक्शनों को जहाँ उपयोगी हो, एक साथ जोड़ सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize TeamsLogons=countif(AppDisplayName has "Teams"), SharePointLogons=countif(AppDisplayName has "SharePoint") by bin(TimeGenerated, 1d)
यह हमारे countif और bin फ़ंक्शनों का संयोजन है, जहाँ हम अपने एप्लिकेशन डिस्प्ले नाम के आधार पर सारांश प्रस्तुत करते हैं और परिणामों को 1d bins में भी रखते हैं।
आप किसी क्वेरी के भीतर आइटमों का एक सेट बना सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppList=make_set(AppDisplayName) by UserPrincipalName
यह उन अनुप्रयोगों की एक सूची आउटपुट करेगा जिनमें [email protected] ने साइन इन किया है, जिसे AppList नामक सूची में संग्रहीत किया जाएगा।
आप इसे हमारे time bin के साथ जोड़ सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppList=make_set(AppDisplayName) by UserPrincipalName, bin(TimeGenerated, 1d)
यह उन अनुप्रयोगों की एक सूची बनाएगा जिनमें [email protected] ने साइन इन किया है, जिसे प्रति दिन एक सूची में विभाजित किया गया है।
render ऑपरेटर KQL को डेटा को विभिन्न प्रारूपों में विज़ुअलाइज़ करने की अनुमति देता है, जैसे piecharts, time या areacharts, और column तथा bar charts।
यदि हम अपने Signinlogs टेबल से उसी उदाहरण का उपयोग करते हैं, तो हम देख सकते हैं कि हम डेटा को विभिन्न तरीकों से विज़ुअलाइज़ कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count()by AppDisplayName | render piechart
यह क्वेरी पिछले 14 दिनों में [email protected] द्वारा साइन-इन किए गए सभी अनुप्रयोगों का सारांश प्रस्तुत करती है, फिर आउटपुट को पाई चार्ट के रूप में दिखाती है।

आप इसे कॉलम चार्ट के रूप में भी प्रस्तुत कर सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppCount=count()by AppDisplayName
| render columnchart

या एक बार चार्ट।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count()by AppDisplayName | render barchart

समय डेटा के लिए, आप पहले अपने डेटा को समय 'बिन्स' में सारांशित करते हैं जैसा कि summarize अनुभाग में बताया गया है, और फिर आप अपने डेटा को एक समय अवधि में विज़ुअलाइज़ कर सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by bin(TimeGenerated, 1d)
| render timechart
यह पिछले 14 दिनों में [email protected] द्वारा प्रति दिन सभी साइन-इन को विज़ुअलाइज़ करता है और इसे timechart के रूप में प्रदर्शित करता है।

आप render का उपयोग areachart के रूप में भी कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize SigninCount=count() by bin(TimeGenerated, 1d) | render areachart

स्तंभ चार्ट और बार चार्ट का उपयोग समय डेटा के साथ भी किया जा सकता है। आपको अपनी बड़ी समय अवधि में प्रत्येक समय 'bin' के लिए एक स्तंभ या बार मिलेगा।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by bin(TimeGenerated, 1d)
| render columnchart
यह हमारे timechart के समान ही query है, लेकिन इसे प्रति दिन एक कॉलम के साथ कॉलम चार्ट के रूप में प्रस्तुत किया गया है।
```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by bin(TimeGenerated, 1d)
| render barchart
और एक बार चार्ट।

कॉलम या बार चार्ट के साथ आप उन्हें एक साथ स्टैक्ड कर सकते हैं (जो डिफ़ॉल्ट है)।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by AppDisplayName, bin(TimeGenerated, 1d)
| render columnchart
यह क्वेरी हमारे खाते के लिए सभी साइन-इन ढूंढती है, प्रति एप्लिकेशन साइन-इन की गिनती करती है, फिर प्रत्येक दिन के लिए एक एकल कॉलम बनाती है।

यदि आप चाहते हैं कि प्रत्येक एप्लिकेशन का अपना कॉलम हो, तो आप इसे अनस्टैक्ड पर सेट कर सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize SigninCount=count() by bin(TimeGenerated, 1d) | render columnchart with (kind=unstacked)

आप KQL के अनुरूप अपने चार्ट के अक्ष और शीर्षक का नाम भी बदल सकते हैं।```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by AppDisplayName, bin(TimeGenerated, 1d)
| render columnchart with (kind=unstacked, ytitle="Total Sign Ins", xtitle="Day", title="Application Signins Per Day")

आप अपने summarize क्रियाओं में तर्क जोड़कर अपने render ऑपरेटर के लिए गतिशील सामग्री बना सकते हैं।```kql SigninLogs | where TimeGenerated > ago(14d) | where ResultType == "0" | summarize TeamsCount=countif(AppDisplayName has "Teams"), OneDrive=countif(AppDisplayName has "OneDrive"), SharePointCount=countif(AppDisplayName has "SharePoint") by bin(TimeGenerated, 1d) | render columnchart with (kind=unstacked, ytitle="Sign In Count", xtitle="Day", title="Teams vs OneDrive vs SharePoint Sign Ins Per Day")
यह क्वेरी आपके टेनेंट में सभी साइन-इन खोजती है, फिर तीन समूहों की गणना करती है — एक जहाँ एप्लिकेशन डिस्प्ले नाम में "Teams" है, एक जहाँ एप्लिकेशन डिस्प्ले नाम में "OneDrive" है और एक जहाँ एप्लिकेशन डिस्प्ले नाम में "SharePoint" है, पिछले 14 दिनों के प्रत्येक दिन के लिए, फिर इसे एक अनस्टैक्ड कॉलम चार्ट के रूप में प्रस्तुत करती है।

### Parse और Split की मूल बातें
Parse और split डेटा की एक स्ट्रिंग को मैचों के आधार पर कई कॉलमों में विस्तारित करने के दो अलग-अलग तरीके हैं। Microsoft Sentinel में इंजेस्ट किए गए बहुत सारे लॉग एक लंबी स्ट्रिंग के रूप में आ सकते हैं (जैसे sysmon), parse और split आपको उन्हें पठनीय डेटा में बदलने की अनुमति देते हैं।
इन उदाहरणों के लिए, हम निम्नलिखित परीक्षण डेटा का उपयोग करेंगे```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account'
];
यह डेटा केवल एक स्ट्रिंग है जो इस प्रकार दिखता है।

हम निम्नलिखित के साथ विशिष्ट डेटा मैचों को पार्स कर सकते हैं```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account' ]; ExampleText | parse TestData with * 'Name=' DisplayName ',' * | project DisplayName
यह Name= और , के बीच के सभी डेटा को 'DisplayName' नामक एक नए कॉलम में पार्स करेगा।

आप उसी कमांड में स्ट्रिंग के साथ मिलान करके कई कॉलम पार्स कर सकते हैं।```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account'
];
ExampleText
| parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' *
| project DisplayName, DomainSuffix, AzureADTenantId
यह तीन नए कॉलम पार्स करता है - DisplayName, DomainSuffix और AzureADTenantId

यह याद रखते हुए कि KQL अपने ऑपरेशन क्रमिक रूप से चलाता है, एक बार पार्स करने के बाद हम नए बनाए गए कॉलम पर फिर से पार्स कर सकते हैं।```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', ]; ExampleText | parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' * | project DisplayName, DomainSuffix, AzureADTenantId | parse DomainSuffix with * '.' TopLevelDomain | project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId
यह हमारे डोमेन को आगे parse करके top level domain खोजता है, इस मामले में एक .com

जब आप parse operator का उपयोग करते हैं, तो KQL आपके सभी डेटा की पंक्तियों से गुज़रता है और उन परिणामों को भी लौटाता है जहाँ कोई मेल नहीं होता है। इसलिए आपके डेटा संरचना के आधार पर आपके पास खाली डेटा की कई पंक्तियाँ आ सकती हैं। यदि हम अपने उदाहरण डेटा में अलग-अलग नामों के साथ एक और पंक्ति जोड़ते हैं और वही query चलाते हैं, तो आपको खाली परिणाम दिखाई देंगे।```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
'Display=Reprise99,UPN=testdomain.com,AadDirectoryId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadObjectId=cf6f2df6-b754-48dc-b7bc-c8339caf211,Name=Test User,AccountType=account'
]
;
ExampleText
| parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' *
| project DisplayName, DomainSuffix, AzureADTenantId
| parse DomainSuffix with * '.' TopLevelDomain
| project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId

इसका मुकाबला करने के लिए आप 'parse-where' ऑपरेटर का उपयोग कर सकते हैं, जो केवल उन्हीं परिणामों को लौटाता है जहाँ आपकी क्वेरी से मेल होते हैं।```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', 'Display=Reprise99,UPN=testdomain.com,AadDirectoryId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadObjectId=cf6f2df6-b754-48dc-b7bc-c8339caf211,Name=Test User,AccountType=account' ] ; ExampleText | parse-where TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' * | project DisplayName, DomainSuffix, AzureADTenantId | parse DomainSuffix with * '.' TopLevelDomain | project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId
हम देख सकते हैं कि हम फिर से एक एकल परिणाम पर लौट आए हैं जहाँ हमें अपने parse पर मैच मिला था।

Split एक string of text को delimiter के आधार पर एक array में विभाजित करता है। यदि हम अपने मूल test data पर वापस जाएँ, तो हम कॉमा चिह्न के आधार पर split कर सकते हैं।```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
]
;
ExampleText
| extend SplitData = split(TestData,',')
| project SplitData
We will be returned an array with our string split out.

Split is index aware so if your data is in the same order, you can split directly into new columns.```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', ] ; ExampleText | extend Name = split(TestData,',')[0] | extend DomainSuffix = split(TestData,',')[1] | extend AzureADTenantId = split(TestData,',')[2] | extend AzureADUserId = split(TestData,',')[3] | extend DisplayName = split(TestData,',')[4] | extend AccountType = split(TestData,',')[5] | project Name, DomainSuffix, AzureADTenantId, AzureADUserId, DisplayName, AccountType
यदि हमें स्ट्रिंग के भीतर अपने डेटा का स्थान पता है, तो हम इसे सीधे नामित कॉलम में विभाजित कर सकते हैं।

एक बार जब हम अपने डेटा को विभाजित कर लेते हैं, तो हम उसे ऐसे क्वेरी कर सकते हैं जैसे कि वह शुरू से ही संरचित था। इसलिए यदि हम अपने डेटा में दूसरा रिकॉर्ड जोड़ते हैं, फिर विशिष्ट मिलान पर क्वेरी करते हैं, तो हमें वही मिलेगा जो हम खोज रहे हैं।```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
'Name=Reprise103,UPNSuffix=testdomain.com,AadTenantId=331c1234-a841-43e5-1d31-12220a5bcee1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User 2,Type=account'
]
;
ExampleText
| extend Name = split(TestData,',')[0]
| extend DomainSuffix = split(TestData,',')[1]
| extend AzureADTenantId = split(TestData,',')[2]
| extend AzureADUserId = split(TestData,',')[3]
| extend DisplayName = split(TestData,',')[4]
| extend AccountType = split(TestData,',')[5]
| project Name, DomainSuffix, AzureADTenantId, AzureADUserId, DisplayName, AccountType
| where Name contains "Reprise99"
हमें केवल एक हिट मिलती है, जहाँ Name में "Reprise99" शामिल है, हमारा दूसरा रिकॉर्ड जहाँ Name में "Reprise103" शामिल है, नहीं मिल पाता।
