PowerShell - ส่งผ่าน FilterScript ไปยัง Where-Object เป็นตัวแปร

Sep 11 2020

ฉันกำลังพยายามรับสคริปต์บล็อก Where-Object FilterScript เป็นตัวแปร แต่ฉันไม่มีโชคไกล เป็นตัวอย่างง่ายๆของสิ่งที่ฉันพยายามทำ:

$test = @('one','two','three') $filter = '$_ -eq "one"' $test | Where-Object -FilterScript { $filter }

ดูเหมือนจะไม่ได้ผล ฉันได้รับคืนทุกองค์ประกอบ ฉันได้ลองแล้ว:

$filter = { $_ -eq "one" } $filter = [scriptblock]::Create($_ -eq 'one')

สิ่งเหล่านี้ส่งคืน:

one
two
three

อย่างไรก็ตามการแทนที่ตัวแปรด้วยตัวกรองจริงจะได้ผลตามที่คาดไว้:

$test | Where-Object -FilterScript { $_ -eq "one" }

สิ่งนี้จะส่งคืนเพียง "หนึ่ง" โดยไม่มี "สอง" และ "สาม" ไม่มีใครรู้ว่าฉันจะทำงานนี้ได้อย่างไร? ตอนแรกฉันลองใช้ Core v7.0.3 แต่ทดสอบบน Windows PowerShell v5.1 ด้วย

คำตอบ

4 Garrett Sep 11 2020 at 15:41

วงเล็บปีกกาหลังจาก-FilterScriptนั้นทำให้คุณสับสนเมื่อตัวแปรมี ScriptBlock คุณไม่จำเป็นต้องใช้วงเล็บปีกกาอีกต่อไป หากคุณมีสิ่งเหล่านี้แสดงว่าเป็นบล็อกสคริปต์ของตัวแปรที่มีสคริปต์บล็อก

$foo = "hi" $foo | gm     (TypeName: String)
{$foo} | gm   (TypeName: ScriptBlock)

หากคุณเพิ่มลง[scriptblock]ใน$filterตัวแปรของคุณเพื่อพิมพ์ตัวแปรอย่างหนักมันจะบ่นเกี่ยวกับการจัดรูปแบบจนกว่าคุณจะเพิ่มวงเล็บปีกกาเมื่อคุณกำหนดตัวแปรของคุณ นี่เป็นวิธีที่ดีเยี่ยมในการตรวจสอบให้แน่ใจว่าวัตถุที่คุณป้อนนั้นWhere-Objectตรงกับประเภทที่คาดไว้สำหรับ-FilterScriptพารามิเตอร์ซึ่งเป็นScriptBlock

มันจะทำงานได้โดยไม่ต้องมีการบังคับประเภทที่แข็งแกร่งเมื่อวงเล็บปีกกาอยู่ในนิยามตัวแปรซึ่งทำให้มันกลายเป็น ScriptBlock แต่ฉันจะปล่อยประเภทไว้ที่นั่นดังนั้นเครื่องยนต์จะบ่นถ้ามีคนถอดเครื่องมือจัดฟันออกและไม่รู้ตัว กำลังเปลี่ยนประเภทตัวแปรของคุณในกระบวนการ

$test = @('one','two','three') [scriptblock]$filter = { $_ -eq "one" } $test | Where-Object -FilterScript $filter
one