การจับชื่อด้วย PowerShell และนิพจน์ทั่วไป
เมื่อคุณเรียนรู้และยอมรับ PowerShell ต่อไป คุณจะพบกับนิพจน์ทั่วไปในที่สุด หวังว่าหลายท่านคงจะมีความรู้พื้นฐานอยู่แล้ว ถ้าไม่ อันดับแรกที่ต้องเริ่มต้นคือการอ่านหัวข้อวิธีใช้ about_regular_expressions ในบทความนี้ ฉันจะแนะนำให้คุณรู้จักกับหัวข้อนิพจน์ทั่วไปขั้นสูง - การจับภาพที่มีชื่อ ฉันยอมรับว่าเมื่อฉันเรียนรู้หัวข้อนี้ครั้งแรก มันทำให้ฉันหัวหมุน แต่หวังว่าฉันจะสามารถชะลอม้าหมุนได้
เริ่มต้นด้วยสตริงเช่นนี้
$t = "2019-06-21 17:12:31Z : 172.16.1.123 [ Begin process data ]"
นี่คือสิ่งที่คุณอาจมีในไฟล์บันทึก .เนื่องจากจุดแข็งของ PowerShell มาจากความสามารถในการทำงานกับออบเจ็กต์ การแปลงไฟล์บันทึกให้เป็นคอลเลกชันของออบเจ็กต์อาจง่ายกว่า
เริ่มต้นด้วยรูปแบบ
เพื่อให้สิ่งนี้ได้ผลและเพื่อให้คุณใช้นิพจน์ทั่วไปได้ คุณต้องรู้ว่าข้อมูลของคุณจะมีลักษณะอย่างไร และจะต้องสอดคล้องกันและสามารถคาดเดาได้ ในตัวอย่างนี้ ฉันมีสตริงวันที่เวลา ที่อยู่ IPv4 และข้อความอยู่ในวงเล็บ ขั้นตอนแรกคือการสร้างรูปแบบนิพจน์ทั่วไปที่ตรงกับองค์ประกอบต่างๆ เหล่านี้ เริ่มต้นด้วยวันที่และเวลา
$t -match "\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z"
รูปแบบบอกว่าให้หาสิ่งที่ขึ้นต้นด้วยตัวเลข 4 หลักพอดี \d หมายถึงตัวเลข และ {4} หมายถึงตัวเลข 4 หลักพอดี จากนั้นจะมีขีดกลางตามด้วยตัวเลข 2 หลัก (\d{2}) อีกขีดกลางและตัวเลข 2 หลัก นั่นควรจะให้วันที่แก่ฉัน แต่มีอีกนิดหน่อย ฉันต้องจับพื้นที่ (\s) จากนั้นฉันก็มีรูปแบบเพื่อให้ตรงกับเวลาที่คุณควรจำได้ในตอนนี้ จุดสิ้นสุดคือตัวอักษร Z
อย่างที่คุณเห็น สิ่งนี้ตรงกับสิ่งที่ฉันต้องการจริงๆ อย่างไรก็ตาม มักจะมีรูปแบบที่คุณสามารถเขียนได้มากกว่าหนึ่งรูปแบบ ฉันกำลังพยายามยึดติดกับรูปแบบที่เรียบง่ายและชัดเจน นิพจน์ทั่วไปสามารถเป็นความลับได้เพียงพอ!
ต่อไปฉันต้องจับคู่ที่อยู่ IP
$t -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
รูปแบบบอกว่าเริ่มต้นด้วยอย่างน้อย 1 หลักและไม่เกิน 3. (\d{1,3}) ตามด้วยจุดตามตัวอักษร (\.) จุดเป็นอักขระนิพจน์ทั่วไปพิเศษที่มีความหมายอะไรก็ได้\คืออักขระหลีกซึ่งบอกให้ PowerShell ค้นหาจุดตามตัวอักษร รูปแบบนี้จะเกิดขึ้นซ้ำกับออคเต็ตที่เหลือ
รูปแบบนี้ไม่ได้ตรวจสอบที่อยู่ เพียงแต่ ดูเหมือน เหมือนกับที่อยู่ IP มีรูปแบบที่จำกัดมากกว่านี้แต่ฉันไม่ต้องการเพิ่มความซับซ้อนอีกต่อไป และในสถานการณ์ของฉัน ฉันรู้ว่าที่อยู่นั้นถูกต้อง
สุดท้ายคือข้อความระหว่างวงเล็บเหลี่ยม
$t -match "\[.*\]"
วงเล็บปีกกาเป็นอักขระนิพจน์ทั่วไปพิเศษ ดังนั้นฉันจึงต้องหลีกเลี่ยง ฉันขอให้จับคู่อักขระใดๆ (.) หลายตัว (*)
กำหนดชื่อ
เมื่อคุณมีรูปแบบที่ตรงกันแล้ว คุณสามารถกำหนดรูปแบบเหล่านั้นด้วยชื่อได้ เค้าโครงทั่วไปมีลักษณะดังนี้:
(?<capture-name>Your-Pattern)
วงเล็บเป็นสิ่งสำคัญ รูปแบบวันที่และเวลาของฉันสามารถกำหนดเป็นการจับภาพที่มีชื่อได้:
(?<date>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z)
นี่คือรูปแบบที่อธิบายข้อความทั้งบรรทัดตั้งแต่ต้นจนจบ
[regex]$rx = '(?<date>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z)\s:\s(?<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s\[\s(?<status>.*)\]'
ฉันได้ปรับแต่งรูปแบบสุดท้ายเพื่อไม่ให้มีวงเล็บเหลี่ยม มีเทคนิคนิพจน์ทั่วไปขั้นสูงอื่นๆ ที่ฉันสามารถใช้ได้ แต่ฉันทำให้มันเรียบง่าย สิ่งสำคัญที่ควรทราบคือฉันกำลังกำหนด $rx ให้เป็นวัตถุชนิดพิเศษ ออบเจ็กต์ regex นี้ช่วยให้ฉันทำได้มากกว่าการใช้ตัวดำเนินการ -match ในสถานการณ์นี้ ฉันสามารถใช้มันเพื่อค้นหาการแข่งขันได้
ดีจัง. แต่ชื่อต่างๆ เข้ามามีบทบาทได้อย่างไร?
การใช้การจับภาพที่มีชื่อใน PowerShell
ในการแข่งขัน คุณจะเห็นพร็อพเพอร์ตี้ Groups นี่คือที่ที่คุณสามารถค้นหาการจับภาพที่มีชื่อได้
การใช้ PowerShell ทำให้ง่ายต่อการรับเฉพาะการจับภาพที่มีชื่อโดยการข้ามกลุ่มแรกที่ตรงกัน
นั่นเกือบจะดูเหมือนวัตถุ! การสร้างวัตถุจริงนั้นใช้เวลาไม่นานนัก
$m.groups | Select-Object -Skip 1 | foreach-object -begin { $h = @{} } -process {
$h.Add($_.name,$_.value.trim())
} -end {
[pscustomobject]$h
}
แม้ว่ามันจะดีกว่าถ้าวันที่เป็นวัตถุ datetime แทนที่จะเป็นสตริง นี่เป็นอีกทางเลือกหนึ่งโดยสมมติว่าคุณรู้ลำดับการจับชื่อของคุณ
$o = [pscustomobject]@{
Date = $m.groups[1].value -as [datetime]
IPAddress = $m.groups[2].value -as [ipaddress]
Status = $m.groups[3].value
}
อย่างที่คุณเห็นนี่คือวัตถุ
ด้วยโค้ดนี้ ฉันสามารถเขียนสคริปต์เพื่อประมวลผลแต่ละบรรทัดของไฟล์บันทึก และสร้างออบเจ็กต์แบบกำหนดเองได้ ทำให้กรอง จัดเรียง หรือทำสิ่งอื่นๆ ที่เกี่ยวข้องกับข้อมูลได้ง่ายขึ้นมาก
แปลงจากข้อความ
หรือวิธีที่ง่ายกว่านั้นล่ะ? ตอนนี้คุณรู้วิธีสร้างรูปแบบนิพจน์ทั่วไปโดยใช้การจับภาพที่มีชื่อแล้ว คุณสามารถใช้คำสั่ง ConvertFrom-Text ในโมดูล PSScriptTools ของฉัน ซึ่งคุณสามารถติดตั้งได้จาก PowerShell Gallery ด้วยคำสั่งนี้ คุณสามารถสร้างโค้ดเพื่อเปลี่ยนเอาต์พุตข้อความใดๆ ให้เป็นออบเจ็กต์ PowerShell ได้
$c = "(?<Protocol>\w{3})\s+(?<LocalIP>(\d{1,3}\.){3}\d{1,3}):(?<LocalPort>\d+)\s+(?<ForeignIP>.*):(?<ForeignPort>\d+)\s+(?<State>\w+)?"
netstat -an | select -skip 4 | convertfrom-text $c | where-object {$_.LocalIP -ne '0.0.0.0'} | format-table -autosize
เมื่อคุณมีทักษะการแสดงออกปกติขั้นพื้นฐานแล้ว คุณจะพบว่าตัวเองใช้ทักษะนั้นบ่อยครั้ง และเช่นเดียวกับภาษาใหม่อื่นๆ ยิ่งคุณใช้มันมากเท่าไร คุณก็จะยิ่งคล่องแคล่วมากขึ้นเท่านั้น