PowerShell - ส่งผ่าน FilterScript ไปยัง Where-Object เป็นตัวแปร
ฉันกำลังพยายามรับสคริปต์บล็อก 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 ด้วย
คำตอบ
วงเล็บปีกกาหลังจาก-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