เกิดอะไรขึ้นกับตัวกรองโฆษณานี้ใน PowerShell


9

ฉันเพิ่งเขียนคำตอบนี้และสะดุดกับสิ่งที่น่าสนใจ

get-aduser -filter {-not (description -eq "auto")} | measure-object

และ

get-aduser -filter {description -ne "auto"} | measure-object

ส่งคืนสองสิ่งที่แตกต่างกันมากเมื่อทำงานกับข้อมูลเดียวกันโดยมีคำสั่งแรกส่งคืนค่าที่คาดหวัง ปรากฏขึ้นอย่างรวดเร็วก่อนว่าผู้ใช้ที่มีค่า Null ในฟิลด์คำอธิบายจะไม่ถูกส่งกลับเป็นคำที่ตรงกันในคำสั่งที่สองแม้ว่า NULL จะไม่ชัดเจนเท่ากับ "อัตโนมัติ"

มีคนในแชทสองคนได้ตรวจสอบเรื่องนี้และยืนยันว่าฉันไม่ได้บ้า เกิดอะไรขึ้นที่นี่?


1
สิ่งที่น่าสนใจคือการส่งผ่านไปยังตำแหน่งที่วัตถุและใช้ตัวกรองที่ไม่ทำงานด้านบน get-aduser -filter * -Properties description | ? $ $. description -ne "อัตโนมัติ"} | วัด
Mike

@ ไมค์ใช่นี้ดูเหมือนจะเป็นลักษณะการทำงานของ-neตัวดำเนินการเปรียบเทียบภายใน-Filterบล็อกเท่านั้น $nullโดยเฉพาะเมื่อค่าการป้อนข้อมูลในการเปรียบเทียบคือ
jscott

1
ชอบและไม่ชอบดูเหมือนจะทำงานในทำนองเดียวกัน {description -notlike "something"} ใช้งานไม่ได้ แต่ {-not (description-like "something")} ไม่ทำงาน นอกจากนี้คนที่ทำงานใช้เวลานานมากในการประเมิน เช่นเดียวกับที่ขาดไม่ได้ประเมินวัตถุทั้งหมดที่ควร
Mike

@ ไมค์ถูกต้อง ที่จริงแล้วฉันสะดุดกับการใช้งาน-notlikeครั้งแรก แต่เปลี่ยนไปใช้-neหลังจากที่ฉันรู้ว่าฉันไม่ได้สิ่งที่ต้องการ TBH ฉันลืมไปเลยว่าฉันเคยลองมาก่อนจนกว่าคุณจะพูดถึงมัน - แต่ฉันก็สามารถทำซ้ำได้เช่นกัน
MDMarra

2
แค่คิด แต่บางที PoSH's -eq/ -neclause พยายามทำตัวเหมือน SQL =/ <>? ใน SQL foo = NULLและfoo <> NULLจะส่งคืนค่าเท็จเสมอเนื่องจาก NULL คือ 'หาที่เปรียบมิได้' - จะมีเพียงตัวดำเนินการพิเศษfoo IS NULLและfoo IS NOT NULLตัวดำเนินการพิเศษเท่านั้น พฤติกรรมจะต้องคล้ายกันใน PoSH ซึ่ง-not (foo -eq "bar")ตัวกรองของคุณจะส่งคืนทุกอย่างที่(foo -eq "bar")ส่งคืน$falseซึ่งfoo -eq $nullจะทำ แต่วิธีการif (!foo -or foo -ne "bar")(เทียบเท่า SQL foo IS NULL OR foo <> 'bar')
jimbobmcgee

คำตอบ:


4

ความแตกต่างที่สำคัญระหว่างทั้งสองคือคำสั่งแรกไม่เกี่ยวข้องกับการเปรียบเทียบค่าโดยตรงเพื่อรับผลลัพธ์ทั้งหมดและคำสั่งที่สองทำ คำสั่งแรกรวมผลลัพธ์ NULL และคำสั่งที่สองไม่ได้ (ตามที่ MDMarra ค้นพบแล้ว) คำสั่งทั้งสองเริ่มต้นด้วย cmdlet นี้:

get-aduser

เมื่อทำตามด้านล่างโปรดจำไว้ว่าผลลัพธ์ของ cmdlet นี้รวมผู้ใช้ AD ทั้งหมดโดยไม่คำนึงถึงสิ่งอื่นใดใน-filterพารามิเตอร์หลังจากนั้น

ทีนี้ลองแยกสองส่วนที่แตกต่างกัน คนแรก:

{-not (description -eq "auto")}

... หมายถึง

  1. "รูปที่แอตทริบิวต์ description เท่ากับสตริงข้อความ" auto "เพื่อเปรียบเทียบการทำงานสตริงจำเป็นต้องมีอยู่ในฟิลด์คำอธิบายสำหรับ-eqโอเปอเรเตอร์เพื่อให้สามารถเปรียบเทียบกับ" auto "ค่า NULL จะหายไปจากสิ่งนี้ การเปรียบเทียบเนื่องจากไม่สามารถเปรียบเทียบ NULL กับค่าสตริงได้
  2. เป็นอิสระจาก -eqพารามิเตอร์ตัวกรองให้ฉันทุกอย่างที่ไม่ใช่ผลลัพธ์(description -eq "auto")ซึ่งจะรวม NULL เนื่องจาก cmdlet ดั้งเดิมget-aduserรวมผู้ใช้ AD ทั้งหมด มันไม่จำเป็นต้องเปรียบเทียบอะไรกับสิ่งอื่นใดกับ-notผู้ให้บริการ มันให้ทุกสิ่งนอกเหนือจากผลลัพธ์ของ(description -eq "auto")ตัวกรอง

ในตัวอย่างของคุณสมมติว่าคุณมีผู้ใช้ AD 1 รายที่มีคำอธิบายเท่ากับ "อัตโนมัติ" สองสามร้อยกับสิ่งอื่นที่ไม่ใช่ "อัตโนมัติ" และอีกสองสามร้อยด้วยคำอธิบายที่เป็นโมฆะ การก้าวผ่านลอจิกคำสั่งมันจะทำ:

  1. ให้ผู้ใช้โฆษณา (get-aduser) ทุกคนที่คำอธิบายเท่ากับ "อัตโนมัติ" - ให้ผู้ใช้ 1 คน
  2. ให้ผู้ใช้ AD ทั้งหมดที่ไม่ใช่สิ่งที่คุณเพิ่งให้ฉัน - ผลลัพธ์คือไม่กี่ร้อยกับอย่างอื่นและอีกสองสามร้อยที่มีค่า NULL

เนื่องจากไม่จำเป็นต้องเปรียบเทียบสิ่งใดกับสิ่งอื่นโดยใช้-notโอเปอเรเตอร์ผลลัพธ์จึงรวมผู้ใช้ NULL description ที่ถูกจับในget-adusercmdlet ดั้งเดิม

คำสั่งที่สอง:

{description -ne "auto"}

... หมายถึง

  1. "เข้าใจว่าแอตทริบิวต์คำอธิบายไม่เท่ากับสตริง" auto "ที่แน่นอนอีกครั้งเพื่อให้การเปรียบเทียบนี้ใช้งานได้สตริงจำเป็นต้องมีอยู่ในฟิลด์คำอธิบายเพื่อให้-neผู้ปฏิบัติงานสามารถเปรียบเทียบกับ" auto "ได้ค่า NULL ถูกดร็อปจากการเปรียบเทียบนี้เนื่องจากไม่สามารถเปรียบเทียบ NULL กับค่าสตริง

ในตัวอย่างของคุณอีกครั้งสมมติว่าคุณมีผู้ใช้ AD 1 รายที่มีคำอธิบายเท่ากับ "อัตโนมัติ" สองสามร้อยกับสิ่งอื่นที่ไม่ใช่ "อัตโนมัติ" และอีกสองสามร้อยด้วยคำอธิบายที่เป็นโมฆะ การก้าวผ่านลอจิกคำสั่งมันจะทำ:

  1. ให้ผู้ใช้โฆษณาทุกคนที่คำอธิบายไม่เท่ากับ "อัตโนมัติ" - ส่งผลให้ผู้ใช้ไม่กี่ร้อยรายที่มีคำอื่น ๆ นอกเหนือจาก "อัตโนมัติ" ในคำอธิบายของพวกเขา ไม่ดึงผู้ใช้ที่มีคำอธิบาย NULL เนื่องจากไม่สามารถเปรียบเทียบ NULL กับสตริงข้อความได้

ความแตกต่างทั้งหมดระหว่างคำสั่งทั้งสองนั้นไม่สามารถหยั่งรู้ได้

การใช้คำสั่งนี้คุณควรจะสามารถจับ NULL ด้วย "- และ" ในนั้นเช่นกัน:

{description -ne "auto" -and description -ne $NULL}

ฉันไม่ใช่ไวยากรณ์ 100% เนื่องจากฉันไม่สามารถทดสอบได้ในตอนนี้และอาจมีวิธีที่ดีกว่าที่จะทำเช่นนี้ เมื่อมันพังลงมันก็ค่อนข้างต่อต้านภูมิอากาศและใช้การพิมพ์จำนวนมากเพื่ออธิบาย แต่ฉันพบเจอกับสิ่งแปลก ๆ เช่นนี้ก่อนที่จะใช้ตัวดำเนินการต่าง ๆ และการลองผิดลองถูกมากมายเพราะฉันจำไม่ได้ว่าถ้ำทั้งหมด ที่ไปพร้อมกับการใช้แต่ละคน

การอ้างอิง: http://technet.microsoft.com/en-us/library/hh847732.aspx :

ผู้ประกอบการเปรียบเทียบ

ใช้ตัวดำเนินการเปรียบเทียบ (-eq, -ne, -gt, -lt, -le, -ge) เพื่อเปรียบเทียบค่าและเงื่อนไขการทดสอบ ตัวอย่างเช่นคุณสามารถเปรียบเทียบสองค่าสตริงเพื่อตรวจสอบว่าพวกเขามีความเท่าเทียมกัน

ตัวดำเนินการเปรียบเทียบรวมตัวดำเนินการจับคู่ (-match, -notmatch) ซึ่งค้นหารูปแบบโดยใช้นิพจน์ทั่วไป แทนที่โอเปอเรเตอร์ (-replace) ซึ่งใช้นิพจน์ทั่วไปเพื่อเปลี่ยนค่าอินพุต ตัวดำเนินการ Like (-like, -notlike) ซึ่งค้นหารูปแบบโดยใช้อักขระตัวแทน (*); และตัวดำเนินการบรรจุ (ใน, -notin, -contain, -notcontain) ซึ่งกำหนดว่าค่าทดสอบจะปรากฏในชุดอ้างอิงหรือไม่

พวกเขายังรวมถึงตัวดำเนินการบิต (-bAND, -bOR, -bXOR, -bNOT) เพื่อจัดการรูปแบบบิตในค่า

สำหรับข้อมูลเพิ่มเติมดู about_Comparison_Operators

ผู้ประกอบการเชิงตรรกะ

ใช้ดำเนินการทางตรรกะ (และอื่น, -or, -xor, -Not!) เพื่อเชื่อมต่องบเงื่อนไขเป็นเงื่อนไขที่ซับซ้อนเดียว ตัวอย่างเช่นคุณสามารถใช้ตัวดำเนินการเชิงตรรกะและตัวกรองวัตถุสร้างเงื่อนไขที่แตกต่างกันสอง

สำหรับข้อมูลเพิ่มเติมดู about_Logical_Operators


ภาพรวมที่ดีแน่นอน แต่ทำไมค่า Null ถึงถูกแยกออกจากตัวดำเนินการ -ne และ -notlike นั่นคือเกาหัวที่แท้จริง ฉันสงสัยว่ามันได้รับการออกแบบโดยมีคำอธิบายข้อมูลจำเพาะ. net ลึกลับหรือหากมีข้อบกพร่องหรือพฤติกรรมที่ไม่คาดคิด?
MDMarra

เดี๋ยวก่อนอ่านเพิ่มเติมให้ละเอียด ดูเหมือนว่าพวกเขาจะเปรียบเทียบสตริงและแอตทริบิวต์ null เท่านั้นจริง ๆ แล้วไม่ใช่สตริงว่างเปล่า ที่น่าสนใจถ้าไม่ได้ใช้งานง่าย
MDMarra

0

การเพิ่มคำถามเก่านี้เมื่อค้นหา:

การใช้ตัวกรองที่มีการจับคู่เชิงลบเช่น -ne หรือ -notlike ไม่รวมผลลัพธ์ที่มีค่าว่างเปล่า เพื่อให้รวมไว้คุณต้องจับคู่อย่างชัดเจนโดยใช้-notlike '*' as -eq ''และ-eq $ NULLไม่ใช่ตัวกรองที่ถูกต้อง หมายเหตุนี่คือการเล่นโวหารที่มี -Filter โดยใช้โดยตรง -LdapFilter DOES ลบค่าว่างเปล่าที่ตรงกัน

นี่คือตัวอย่างตัวกรองและ LdapFilter ของการจับคู่แบบหลายตัวที่มีค่าลบ:

Get-ADUser -Filter { mail -like '*example*' -and (description -ne 'example' -or description -notlike '*') }

Get-ADUser -LdapFilter '(&(mail=*example*)(!description=example))'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.