ค้นหาเว็บไซต์

ทุกสิ่งที่คุณอยากรู้เกี่ยวกับคำสั่ง if


เช่นเดียวกับภาษาอื่นๆ หลายภาษา PowerShell มีคำสั่งสำหรับการรันโค้ดตามเงื่อนไขในสคริปต์ของคุณ หนึ่งในคำสั่งเหล่านั้นคือคำสั่ง If วันนี้เราจะเจาะลึกหนึ่งในคำสั่งพื้นฐานที่สุดใน PowerShell

บันทึก

ต้นฉบับของบทความนี้ปรากฏบนบล็อกที่เขียนโดย @KevinMarquette ทีม PowerShell ขอขอบคุณ Kevin สำหรับการแบ่งปันเนื้อหานี้กับเรา โปรดตรวจสอบบล็อกของเขาที่ PowerShellExplained.com

การดำเนินการตามเงื่อนไข

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

คำสั่ง if

นี่คือตัวอย่างพื้นฐานของคำสั่ง if:

$condition = $true
if ( $condition )
{
    Write-Output "The condition was true"
}

สิ่งแรกที่คำสั่ง if ทำคือประเมินนิพจน์ในวงเล็บ หากประเมินเป็น $true แสดงว่าดำเนินการ scriptblock ในเครื่องหมายปีกกา หากค่าเป็น $false ระบบจะข้ามบล็อกสคริปต์นั้น

ในตัวอย่างก่อนหน้านี้ คำสั่ง if เป็นเพียงการประเมินตัวแปร $condition มันเป็น $true และจะต้องดำเนินการคำสั่ง Write-Output ภายใน scriptblock

ในบางภาษา คุณสามารถวางโค้ดบรรทัดเดียวหลังคำสั่ง if และโค้ดจะถูกดำเนินการ นั่นไม่ใช่กรณีใน PowerShell คุณต้องระบุ scriptblock แบบเต็มด้วยเครื่องหมายปีกกาเพื่อให้ทำงานได้อย่างถูกต้อง

ตัวดำเนินการเปรียบเทียบ

การใช้งานทั่วไปของคำสั่ง if คือการเปรียบเทียบสองรายการระหว่างกัน PowerShell มีตัวดำเนินการพิเศษสำหรับสถานการณ์การเปรียบเทียบที่แตกต่างกัน เมื่อคุณใช้ตัวดำเนินการเปรียบเทียบ ค่าทางด้านซ้ายมือจะถูกเปรียบเทียบกับค่าทางด้านขวามือ

-eq เพื่อความเท่าเทียมกัน

-eq จะตรวจสอบความเท่าเทียมกันระหว่างสองค่าเพื่อให้แน่ใจว่ามีค่าเท่ากัน

$value = Get-MysteryValue
if ( 5 -eq $value )
{
    # do something
}

ในตัวอย่างนี้ ฉันใช้ค่าที่ทราบเป็น 5 และเปรียบเทียบกับ $value ของฉันเพื่อดูว่าตรงกันหรือไม่

กรณีการใช้งานหนึ่งที่เป็นไปได้คือการตรวจสอบสถานะของค่าก่อนที่คุณจะดำเนินการกับค่านั้น คุณสามารถรับบริการและตรวจสอบว่าสถานะกำลังทำงานอยู่ก่อนที่คุณจะเรียกว่า Restart-Service

เป็นเรื่องปกติในภาษาอื่นๆ เช่น C# ที่จะใช้ == เพื่อความเท่าเทียมกัน (เช่น: 5 == $value) แต่ใช้ไม่ได้กับ PowerShell ข้อผิดพลาดทั่วไปอีกประการหนึ่งที่ผู้คนทำคือการใช้เครื่องหมายเท่ากับ (เช่น 5=$value) ที่สงวนไว้สำหรับการกำหนดค่าให้กับตัวแปร การวางค่าที่ทราบไว้ทางซ้าย จะทำให้ทำผิดพลาดได้ยากขึ้น

โอเปอเรเตอร์นี้ (และอื่นๆ) มีรูปแบบที่แตกต่างกันเล็กน้อย

  • -eq ความเท่าเทียมกันโดยไม่คำนึงถึงขนาดตัวพิมพ์
  • -ieq ความเท่าเทียมกันโดยไม่คำนึงถึงขนาดตัวพิมพ์
  • -ceq ความเท่าเทียมกันแบบคำนึงถึงขนาดตัวพิมพ์

-ไม่เท่ากัน

ตัวดำเนินการหลายตัวมีตัวดำเนินการที่เกี่ยวข้องซึ่งกำลังตรวจสอบผลลัพธ์ที่ตรงกันข้าม -ne ตรวจสอบว่าค่าไม่เท่ากัน

if ( 5 -ne $value )
{
    # do something
}

ใช้สิ่งนี้เพื่อให้แน่ใจว่าการดำเนินการจะดำเนินการเฉพาะในกรณีที่ค่าไม่ใช่ 5 กรณีการใช้งานที่ดีซึ่งควรตรวจสอบว่าบริการอยู่ในสถานะกำลังทำงานอยู่หรือไม่ก่อนที่คุณจะพยายามเริ่มใช้งาน

รูปแบบต่างๆ:

  • -ne ไม่คำนึงถึงขนาดตัวพิมพ์
  • -ine ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -cne คำนึงถึงขนาดตัวพิมพ์ไม่เท่ากัน

สิ่งเหล่านี้คือรูปแบบผกผันของ -eq ฉันจะจัดกลุ่มประเภทเหล่านี้เข้าด้วยกันเมื่อฉันแสดงรายการรูปแบบต่างๆ สำหรับโอเปอเรเตอร์อื่นๆ

-gt -ge -lt -le มากกว่าหรือน้อยกว่า

ตัวดำเนินการเหล่านี้ใช้ในการตรวจสอบว่าค่ามีขนาดใหญ่หรือเล็กกว่าค่าอื่นหรือไม่ -gt -ge -lt -le ย่อมาจาก GreaterThan, GreaterThanOrEqual, LessThan และ LessThanOrEqual

if ( $value -gt 5 )
{
    # do something
}

รูปแบบต่างๆ:

  • -gt มากกว่า
  • -igt มากกว่า ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่
  • -cgt มากกว่า คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -ge มากกว่าหรือเท่ากับ
  • -ige มากกว่าหรือเท่ากับ ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่
  • -cge มากกว่าหรือเท่ากับ คำนึงถึงขนาดตัวพิมพ์
  • -lt น้อยกว่า
  • -ilt น้อยกว่า ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -clt น้อยกว่า คำนึงถึงขนาดตัวพิมพ์
  • -le น้อยกว่าหรือเท่ากับ
  • -ile น้อยกว่าหรือเท่ากับ ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -cle น้อยกว่าหรือเท่ากับ คำนึงถึงขนาดตัวพิมพ์

ฉันไม่รู้ว่าทำไมคุณถึงใช้ตัวเลือกที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่สำหรับตัวดำเนินการเหล่านี้

- เหมือนการแข่งขันไวด์การ์ด

PowerShell มีไวยากรณ์การจับคู่รูปแบบที่ใช้ไวด์การ์ดของตัวเอง และคุณสามารถใช้กับตัวดำเนินการ -like ได้ รูปแบบไวด์การ์ดเหล่านี้ค่อนข้างพื้นฐาน

  • ? จับคู่อักขระเดี่ยวใดๆ
  • * จับคู่อักขระจำนวนเท่าใดก็ได้
$value = 'S-ATX-SQL01'
if ( $value -like 'S-*-SQL??')
{
    # do something
}

สิ่งสำคัญคือต้องชี้ให้เห็นว่ารูปแบบนั้นตรงกับสตริงทั้งหมด หากคุณต้องการจับคู่บางสิ่งที่อยู่ตรงกลางของสตริง คุณต้องวาง * ที่ปลายทั้งสองด้านของสตริง

$value = 'S-ATX-SQL02'
if ( $value -like '*SQL*')
{
    # do something
}

รูปแบบต่างๆ:

  • ไวด์การ์ด -like ที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -ilike ไวด์การ์ดที่ไม่คำนึงถึงขนาดตัวพิมพ์
  • -clike ไวด์การ์ดที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -notlike ไวด์การ์ดไม่ตรงกัน
  • -inotlike ไวด์การ์ดไม่ตรงกัน
  • -cnotlike ไวด์การ์ดที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ไม่ตรงกัน

- จับคู่นิพจน์ทั่วไป

ตัวดำเนินการ -match ช่วยให้คุณสามารถตรวจสอบสตริงสำหรับการจับคู่ตามนิพจน์ทั่วไป ใช้สิ่งนี้เมื่อรูปแบบไวด์การ์ดไม่ยืดหยุ่นเพียงพอสำหรับคุณ

$value = 'S-ATX-SQL01'
if ( $value -match 'S-\w\w\w-SQL\d\d')
{
    # do something
}

รูปแบบ regex จะจับคู่ที่ใดก็ได้ในสตริงตามค่าเริ่มต้น ดังนั้นคุณจึงสามารถระบุสตริงย่อยที่คุณต้องการจับคู่ได้ดังนี้:

$value = 'S-ATX-SQL01'
if ( $value -match 'SQL')
{
    # do something
}

Regex เป็นภาษาที่ซับซ้อนในตัวเองและควรค่าแก่การพิจารณา ฉันพูดถึง -match เพิ่มเติมและวิธีต่างๆ มากมายในการใช้ regex ในบทความอื่น

รูปแบบต่างๆ:

  • -match regex ที่ไม่คำนึงถึงขนาดตัวพิมพ์
  • -imatch regex ที่ไม่คำนึงถึงขนาดตัวพิมพ์
  • -cmatch regex แบบคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -notmatch regex ที่ไม่ตรงตามตัวพิมพ์ใหญ่-เล็กไม่ตรงกัน
  • -inotmatch regex ที่ไม่ตรงตามตัวพิมพ์ใหญ่-เล็กไม่ตรงกัน
  • -cnotmatch regex แบบคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ไม่ตรงกัน

-เป็นประเภท

คุณสามารถตรวจสอบประเภทของค่าได้ด้วยตัวดำเนินการ -is

if ( $value -is [string] )
{
    # do something
}

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

if ( $Service -isnot [System.ServiceProcess.ServiceController] )
{
    $Service = Get-Service -Name $Service
}

รูปแบบต่างๆ:

  • -คือ ประเภท
  • -isnot ไม่ใช่ประเภท

ผู้ประกอบการรวบรวม

เมื่อคุณใช้ตัวดำเนินการก่อนหน้าที่มีค่าเดียว ผลลัพธ์จะเป็น $true หรือ $false สิ่งนี้จะได้รับการจัดการแตกต่างออกไปเล็กน้อยเมื่อทำงานกับคอลเลกชัน แต่ละรายการในคอลเลกชันจะได้รับการประเมิน และผู้ดำเนินการส่งคืนทุกค่าที่ประเมินเป็น $true

PS> 1,2,3,4 -eq 3
3

สิ่งนี้ยังคงทำงานได้อย่างถูกต้องในคำสั่ง if ดังนั้นค่าจะถูกส่งกลับโดยโอเปอเรเตอร์ของคุณ ดังนั้นคำสั่งทั้งหมดจึงเป็น $true

$array = 1..6
if ( $array -gt 3 )
{
    # do something
}

มีกับดักเล็กๆ ซ่อนอยู่ในรายละเอียดซึ่งฉันต้องชี้ให้เห็น เมื่อใช้ตัวดำเนินการ -ne ด้วยวิธีนี้ เป็นเรื่องง่ายที่จะมองตรรกะย้อนกลับโดยไม่ได้ตั้งใจ การใช้ -ne กับคอลเลกชันจะส่งคืน $true หากรายการใดๆ ในคอลเลกชันไม่ตรงกับค่าของคุณ

PS> 1,2,3 -ne 4
1
2
3

นี่อาจดูเหมือนเป็นกลอุบายที่ชาญฉลาด แต่เรามีตัวดำเนินการ -contains และ -in ที่จัดการสิ่งนี้ได้อย่างมีประสิทธิภาพมากขึ้น และ -notcontains ทำสิ่งที่คุณคาดหวัง

-contains

ตัวดำเนินการ -contains จะตรวจสอบคอลเลกชันสำหรับค่าของคุณ ทันทีที่พบรายการที่ตรงกัน มันจะส่งคืน $true

$array = 1..6
if ( $array -contains 3 )
{
    # do something
}

นี่เป็นวิธีที่เหมาะสมที่สุดในการดูว่าคอลเลกชันมีมูลค่าของคุณหรือไม่ การใช้ Where-Object (หรือ -eq) เป็นการเดินผ่านรายการทั้งหมดทุกครั้งและช้าลงอย่างมาก

รูปแบบต่างๆ:

  • -contains การจับคู่แบบไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -icontains การจับคู่แบบไม่คำนึงถึงขนาดตัวพิมพ์
  • -ccontains การจับคู่แบบคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -notcontains ไม่คำนึงถึงขนาดตัวพิมพ์
  • -inotcontains ไม่คำนึงถึงขนาดตัวพิมพ์
  • -cnotcontains คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ไม่ตรงกัน

-in

ตัวดำเนินการ -in ก็เหมือนกับตัวดำเนินการ -contains ยกเว้นว่าคอลเลกชันจะอยู่ทางด้านขวามือ

$array = 1..6
if ( 3 -in $array )
{
    # do something
}

รูปแบบต่างๆ:

  • -in ตรงกันโดยไม่คำนึงถึงขนาดตัวพิมพ์
  • -iin การจับคู่แบบไม่คำนึงถึงขนาดตัวพิมพ์
  • -cin ตรงตามตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • -notin ไม่คำนึงถึงขนาดตัวพิมพ์
  • -inotin ไม่คำนึงถึงขนาดตัวพิมพ์
  • -cnotin คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ไม่ตรงกัน

ตัวดำเนินการเชิงตรรกะ

ตัวดำเนินการเชิงตรรกะใช้เพื่อกลับหรือรวมนิพจน์อื่นๆ

-not

ตัวดำเนินการ -not พลิกนิพจน์จาก $false เป็น $true หรือจาก $true เป็น $เท็จ. นี่คือตัวอย่างที่เราต้องการดำเนินการเมื่อ Test-Path เป็น $false

if ( -not ( Test-Path -Path $path ) )

ตัวดำเนินการส่วนใหญ่ที่เราพูดถึงมีรูปแบบที่คุณไม่จำเป็นต้องใช้ตัวดำเนินการ -not แต่ยังมีบางครั้งที่มันมีประโยชน์

- ตัวดำเนินการ

คุณสามารถใช้ ! เป็นนามแฝงสำหรับ -not

if ( -not $value ){}
if ( !$value ){}

คุณอาจเห็น ! ถูกใช้มากขึ้นโดยผู้ที่มาจากภาษาอื่นเช่น C# ฉันชอบพิมพ์ออกมาเพราะฉันพบว่ามันยากที่จะเห็นเมื่อดูสคริปต์อย่างรวดเร็ว

-and

คุณสามารถรวมนิพจน์เข้ากับตัวดำเนินการ -และ เมื่อคุณทำเช่นนั้น ทั้งสองฝ่ายจะต้อง $true เพื่อให้นิพจน์ทั้งหมดเป็น $true

if ( ($age -gt 13) -and ($age -lt 55) )

ในตัวอย่างนี้ $age จะต้องมีอายุ 13 ปีขึ้นไปสำหรับด้านซ้าย และน้อยกว่า 55 สำหรับด้านขวา ฉันเพิ่มวงเล็บเพิ่มเติมเพื่อให้ชัดเจนในตัวอย่างนี้ แต่ก็เป็นทางเลือกตราบใดที่สำนวนนั้นเรียบง่าย นี่คือตัวอย่างเดียวกันที่ไม่มีพวกเขา

if ( $age -gt 13 -and $age -lt 55 )

การประเมินเกิดขึ้นจากซ้ายไปขวา หากรายการแรกประเมินเป็น $false รายการดังกล่าวจะออกก่อนกำหนดและไม่สามารถเปรียบเทียบได้ถูกต้อง สิ่งนี้มีประโยชน์เมื่อคุณต้องการตรวจสอบให้แน่ใจว่ามีค่าอยู่ก่อนที่จะใช้งาน ตัวอย่างเช่น Test-Path ส่งข้อผิดพลาดหากคุณกำหนดเส้นทาง $null

if ( $null -ne $path -and (Test-Path -Path $path) )

-or

-หรือ ช่วยให้คุณสามารถระบุสองนิพจน์และส่งกลับ $true หากหนึ่งในนั้นคือ $true

if ( $age -le 13 -or $age -ge 55 )

เช่นเดียวกับตัวดำเนินการ -และ การประเมินจะเกิดขึ้นจากซ้ายไปขวา ยกเว้นว่าหากส่วนแรกเป็น $true คำสั่งทั้งหมดจะเป็น $true และจะไม่ประมวลผลส่วนที่เหลือของนิพจน์

จดบันทึกวิธีการทำงานของไวยากรณ์สำหรับตัวดำเนินการเหล่านี้ด้วย คุณต้องมีนิพจน์สองรายการแยกกัน ฉันเคยเห็นผู้ใช้พยายามทำสิ่งนี้ $value -eq 5 -or 6 โดยไม่ได้ตระหนักถึงข้อผิดพลาด

-xor พิเศษหรือ

อันนี้ผิดปกติเล็กน้อย -xor อนุญาตให้มีนิพจน์เดียวประเมินเป็น $true ดังนั้น หากทั้งสองรายการเป็น $false หรือทั้งสองรายการเป็น $true ดังนั้นนิพจน์ทั้งหมดจะเป็น $false อีกวิธีในการดูสิ่งนี้คือนิพจน์จะเป็น $true เท่านั้น เมื่อผลลัพธ์ของนิพจน์แตกต่างกัน

เป็นเรื่องยากที่ใครๆ จะใช้ตัวดำเนินการเชิงตรรกะนี้ และฉันไม่สามารถคิดตัวอย่างที่ดีได้ว่าทำไมฉันถึงใช้มัน

ตัวดำเนินการ Bitwise

ตัวดำเนินการระดับบิตจะทำการคำนวณบิตภายในค่าและสร้างค่าใหม่ตามผลลัพธ์ การสอนตัวดำเนินการระดับบิตนั้นอยู่นอกเหนือขอบเขตของบทความนี้ แต่นี่คือรายการของพวกเขา

  • -band ไบนารีและ
  • -bor ไบนารีหรือ
  • -bxor ไบนารีพิเศษหรือ
  • -bnot ไบนารี่ ไม่
  • -shl เลื่อนไปทางซ้าย
  • -shr เลื่อนไปทางขวา

นิพจน์ PowerShell

เราสามารถใช้ PowerShell ปกติภายในคำสั่งเงื่อนไขได้

if ( Test-Path -Path $Path )

Test-Path ส่งคืน $true หรือ $false เมื่อดำเนินการ นอกจากนี้ยังใช้กับคำสั่งที่ส่งคืนค่าอื่นๆ ด้วย

if ( Get-Process Notepad* )

โดยจะประเมินเป็น $true หากมีกระบวนการส่งคืน และ $false หากไม่มี การใช้นิพจน์ไปป์ไลน์หรือคำสั่ง PowerShell อื่นๆ ในลักษณะนี้เหมาะสมอย่างยิ่ง:

if ( Get-Process | Where Name -eq Notepad )

นิพจน์เหล่านี้สามารถนำมารวมกันโดยใช้ตัวดำเนินการ -และ และ -หรือ แต่คุณอาจต้องใช้วงเล็บเพื่อแยกนิพจน์เหล่านี้ออกเป็นนิพจน์ย่อย

if ( (Get-Process) -and (Get-Service) )

กำลังตรวจสอบ $null

การไม่มีผลลัพธ์หรือค่า $null จะประเมินเป็น $false ในคำสั่ง if เมื่อตรวจสอบ $null โดยเฉพาะ แนวทางปฏิบัติที่ดีที่สุดคือวาง $null ทางด้านซ้ายมือ

if ( $null -eq $value )

มีความแตกต่างเล็กน้อยเมื่อต้องจัดการกับค่า $null ใน PowerShell หากคุณสนใจที่จะเจาะลึกยิ่งขึ้น ฉันมีบทความเกี่ยวกับทุกสิ่งที่คุณอยากรู้เกี่ยวกับ $null

การกำหนดตัวแปรภายในเงื่อนไข

เกือบลืมใส่อันนี้ไป จน ประสูร การุนันท์ วี เตือนให้นึกถึงเรื่องนี้

if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}

โดยปกติเมื่อคุณกำหนดค่าให้กับตัวแปร ค่าจะไม่ถูกส่งผ่านไปยังไปป์ไลน์หรือคอนโซล เมื่อคุณกำหนดตัวแปรในนิพจน์ย่อย ตัวแปรนั้นจะถูกส่งต่อไปยังไปป์ไลน์

PS> $first = 1
PS> ($second = 2)
2

ดูว่าการกำหนด $first ไม่มีเอาต์พุตและการมอบหมาย $second ทำอย่างไร เมื่อการมอบหมายเสร็จสิ้นในคำสั่ง if ก็จะดำเนินการเหมือนกับการมอบหมาย $second ด้านบน นี่คือตัวอย่างที่ชัดเจนเกี่ยวกับวิธีการใช้งาน:

if ( $process = Get-Process Notepad* )
{
    $process | Stop-Process
}

หาก $process ได้รับการกำหนดค่า ดังนั้นคำสั่งจะเป็น $true และ $process จะถูกหยุด

ตรวจสอบให้แน่ใจว่าคุณไม่สับสนกับ -eq เนื่องจากนี่ไม่ใช่การตรวจสอบความเท่าเทียมกัน นี่เป็นคุณลักษณะที่คลุมเครือมากขึ้นซึ่งคนส่วนใหญ่ไม่รู้ว่าวิธีนี้ใช้ได้ผล

การกำหนดตัวแปรจาก scriptblock

คุณยังสามารถใช้คำสั่ง if scriptblock เพื่อกำหนดค่าให้กับตัวแปรได้

$discount = if ( $age -ge 55 )
{
    Get-SeniorDiscount
}
elseif ( $age -le 13 )
{
    Get-ChildDiscount
}
else
{
    0.00
}

แต่ละบล็อกสคริปต์กำลังเขียนผลลัพธ์ของคำสั่งหรือค่าเป็นเอาต์พุต เราสามารถกำหนดผลลัพธ์ของคำสั่ง if ให้กับตัวแปร $discount ตัวอย่างนั้นสามารถกำหนดค่าเหล่านั้นให้กับตัวแปร $discount โดยตรงในแต่ละ scriptblock ได้อย่างง่ายดายพอๆ กัน ฉันไม่สามารถพูดได้ว่าฉันใช้สิ่งนี้กับคำสั่ง if บ่อยครั้ง แต่ฉันมีตัวอย่างที่ฉันใช้สิ่งนี้เมื่อเร็ว ๆ นี้

เส้นทางการดำเนินการสำรอง

คำสั่ง if ช่วยให้คุณสามารถระบุการดำเนินการได้ ไม่เพียงแต่เมื่อคำสั่งนั้นเป็น $true เท่านั้น แต่ยังรวมถึงเมื่อเป็น $false ด้วย นี่คือที่มาของคำสั่ง else

อื่น

คำสั่ง else เป็นส่วนสุดท้ายของคำสั่ง if เสมอเมื่อใช้

if ( Test-Path -Path $Path -PathType Leaf )
{
    Move-Item -Path $Path -Destination $archivePath
}
else
{
    Write-Warning "$path doesn't exist or isn't a file."
}

ในตัวอย่างนี้ เราจะตรวจสอบ $path เพื่อให้แน่ใจว่าเป็นไฟล์ หากเราพบไฟล์เราจะย้ายมัน ถ้าไม่เช่นนั้นเราจะเขียนคำเตือน ตรรกะการแยกสาขาประเภทนี้เป็นเรื่องธรรมดามาก

ซ้อนถ้า

คำสั่ง if และ else รับบล็อกสคริปต์ ดังนั้นเราสามารถวางคำสั่ง PowerShell ใด ๆ ไว้ข้างในได้ รวมถึงคำสั่ง if อื่นด้วย สิ่งนี้ทำให้คุณสามารถใช้ตรรกะที่ซับซ้อนมากขึ้นได้

if ( Test-Path -Path $Path -PathType Leaf )
{
    Move-Item -Path $Path -Destination $archivePath
}
else
{
    if ( Test-Path -Path $Path )
    {
        Write-Warning "A file was required but a directory was found instead."
    }
    else
    {
        Write-Warning "$path could not be found."
    }
}

ในตัวอย่างนี้ เราทดสอบเส้นทางแห่งความสุขก่อน แล้วจึงดำเนินการตามนั้น หากไม่สำเร็จ เราจะตรวจสอบอีกครั้งและให้ข้อมูลรายละเอียดเพิ่มเติมแก่ผู้ใช้

อย่างอื่น

เราไม่ได้จำกัดอยู่เพียงการตรวจสอบแบบมีเงื่อนไขเพียงครั้งเดียว เราสามารถเชื่อมโยงคำสั่ง if และ else เข้าด้วยกัน แทนที่จะซ้อนกันโดยใช้คำสั่ง elseif

if ( Test-Path -Path $Path -PathType Leaf )
{
    Move-Item -Path $Path -Destination $archivePath
}
elseif ( Test-Path -Path $Path )
{
    Write-Warning "A file was required but a directory was found instead."
}
else
{
    Write-Warning "$path could not be found."
}

การดำเนินการเกิดขึ้นจากบนลงล่าง คำสั่ง if บนสุดจะถูกประเมินก่อน หากนั่นคือ $false มันจะเลื่อนลงไปที่ elseif หรือ else ถัดไปในรายการ else สุดท้ายนั้นเป็นการกระทำเริ่มต้นที่จะดำเนินการหากไม่มีสิ่งอื่นใดส่งคืน $true

สวิตช์

ณ จุดนี้ ฉันต้องพูดถึงคำสั่ง switch มันมีไวยากรณ์ทางเลือกสำหรับการเปรียบเทียบหลายค่าด้วยค่า ด้วย สวิตช์ คุณจะระบุนิพจน์และผลลัพธ์นั้นจะถูกเปรียบเทียบกับค่าที่แตกต่างกันหลายค่า หากค่าใดค่าหนึ่งตรงกัน บล็อกโค้ดที่ตรงกันจะถูกดำเนินการ ลองดูตัวอย่างนี้:

$itemType = 'Role'
switch ( $itemType )
{
    'Component'
    {
        'is a component'
    }
    'Role'
    {
        'is a role'
    }
    'Location'
    {
        'is a location'
    }
}

มีค่าที่เป็นไปได้สามค่าที่สามารถตรงกับ $itemType ในกรณีนี้ จะจับคู่กับ Role ฉันใช้ตัวอย่างง่ายๆ เพื่อให้คุณได้เห็นตัวดำเนินการ switch ฉันพูดคุยเพิ่มเติมเกี่ยวกับทุกสิ่งที่คุณอยากรู้เกี่ยวกับคำสั่ง switch ในบทความอื่น

อาร์เรย์แบบอินไลน์

ฉันมีฟังก์ชันที่เรียกว่า Invoke-SnowSql ซึ่งเรียกใช้งานปฏิบัติการด้วยอาร์กิวเมนต์บรรทัดคำสั่งหลายรายการ นี่คือคลิปจากฟังก์ชันที่ฉันสร้างอาร์เรย์ของอาร์กิวเมนต์

$snowSqlParam = @(
    '--accountname', $Endpoint
    '--username', $Credential.UserName
    '--option', 'exit_on_error=true'
    '--option', 'output_format=csv'
    '--option', 'friendly=false'
    '--option', 'timing=false'
    if ($Debug)
    {
        '--option', 'log_level=DEBUG'
    }
    if ($Path)
    {
        '--filename', $Path
    }
    else
    {
        '--query', $singleLineQuery
    }
)

ตัวแปร $Debug และ $Path เป็นพารามิเตอร์ในฟังก์ชันที่จัดทำโดยผู้ใช้ปลายทาง ฉันประเมินพวกมันแบบอินไลน์ภายในการเริ่มต้นอาร์เรย์ของฉัน หาก $Debug เป็นจริง ค่าเหล่านั้นจะอยู่ใน $snowSqlParam ในตำแหน่งที่ถูกต้อง เช่นเดียวกันถือเป็นจริงสำหรับตัวแปร $Path

ลดความซับซ้อนของการดำเนินงานที่ซับซ้อน

หลีกเลี่ยงไม่ได้ที่คุณจะพบสถานการณ์ที่มีการเปรียบเทียบมากเกินไปที่จะตรวจสอบ และคำสั่ง If ของคุณเลื่อนออกไปทางด้านขวาของหน้าจอ

$user = Get-ADUser -Identity $UserName
if ( $null -ne $user -and $user.Department -eq 'Finance' -and $user.Title -match 'Senior' -and $user.HomeDrive -notlike '\\server\*' )
{
    # Do Something
}

อาจอ่านยากและทำให้คุณมีแนวโน้มที่จะทำผิดพลาดมากขึ้น มีบางสิ่งที่เราสามารถทำได้เกี่ยวกับเรื่องนั้น

ต่อแถว

มีโอเปอเรเตอร์บางตัวใน PowerShell ที่ให้คุณตัดคำสั่งไปยังบรรทัดถัดไป ตัวดำเนินการเชิงตรรกะ -และ และ -or เป็นตัวดำเนินการที่ดีที่จะใช้หากคุณต้องการแบ่งนิพจน์ของคุณออกเป็นหลายบรรทัด

if ($null -ne $user -and
    $user.Department -eq 'Finance' -and
    $user.Title -match 'Senior' -and
    $user.HomeDrive -notlike '\\server\*'
)
{
    # Do Something
}

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

ผลลัพธ์การคำนวณล่วงหน้า

เราสามารถนำคำสั่งนั้นออกจากคำสั่ง if และตรวจสอบเฉพาะผลลัพธ์เท่านั้น

$needsSecureHomeDrive = $null -ne $user -and
    $user.Department -eq 'Finance' -and
    $user.Title -match 'Senior' -and
    $user.HomeDrive -notlike '\\server\*'

if ( $needsSecureHomeDrive )
{
    # Do Something
}

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

หลายคำสั่ง if

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

$skipUser = $false

if( $null -eq $user )
{
    $skipUser = $true
}

if( $user.Department -ne 'Finance' )
{
    Write-Verbose "isn't in Finance department"
    $skipUser = $true
}

if( $user.Title -match 'Senior' )
{
    Write-Verbose "Doesn't have Senior title"
    $skipUser = $true
}

if( $user.HomeDrive -like '\\server\*' )
{
    Write-Verbose "Home drive already configured"
    $skipUser = $true
}

if ( -not $skipUser )
{
    # do something
}

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

ข้อเสียที่ชัดเจนคือต้องเขียนโค้ดมากกว่ามาก โค้ดมีความซับซ้อนมากขึ้นเมื่อพิจารณาเนื่องจากใช้ตรรกะบรรทัดเดียวและขยายออกเป็น 25 บรรทัดขึ้นไป

การใช้ฟังก์ชั่น

นอกจากนี้เรายังสามารถย้ายตรรกะการตรวจสอบทั้งหมดนั้นไปไว้ในฟังก์ชันได้ ดูชัดๆ ว่าสะอาดแค่ไหน..

if ( Test-SecureDriveConfiguration -ADUser $user )
{
    # do something
}

คุณยังคงต้องสร้างฟังก์ชันเพื่อทำการตรวจสอบ แต่มันทำให้โค้ดนี้ทำงานได้ง่ายขึ้นมาก ทำให้โค้ดนี้ง่ายต่อการทดสอบ ในการทดสอบของคุณ คุณสามารถจำลองการเรียก Test-ADDriveConfiguration และคุณต้องการการทดสอบเพียงสองครั้งสำหรับฟังก์ชันนี้ ช่องหนึ่งส่งคืน $true และอีกช่องส่งคืน $false การทดสอบฟังก์ชันอื่นนั้นง่ายกว่าเนื่องจากมีขนาดเล็กมาก

เนื้อความของฟังก์ชันนั้นอาจเป็นบรรทัดเดียวที่เราเริ่มต้นด้วยหรือตรรกะแบบกระจายที่เราใช้ในส่วนสุดท้าย วิธีนี้ใช้ได้ผลดีกับทั้งสองสถานการณ์และช่วยให้คุณเปลี่ยนการใช้งานในภายหลังได้อย่างง่ายดาย

การจัดการข้อผิดพลาด

การใช้คำสั่ง if ที่สำคัญอย่างหนึ่งคือการตรวจสอบเงื่อนไขข้อผิดพลาดก่อนที่คุณจะพบข้อผิดพลาด ตัวอย่างที่ดีคือการตรวจสอบว่ามีโฟลเดอร์อยู่แล้วก่อนที่คุณจะพยายามสร้างมันขึ้นมา

if ( -not (Test-Path -Path $folder) )
{
    New-Item -Type Directory -Path $folder
}

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

หากคุณต้องการเจาะลึกเพิ่มเติมอีกเล็กน้อยเกี่ยวกับการจัดการข้อยกเว้นที่เกิดขึ้นจริง ฉันมีบทความเกี่ยวกับทุกสิ่งที่คุณต้องการทราบเกี่ยวกับข้อยกเว้น

คำพูดสุดท้าย

คำสั่ง if เป็นคำสั่งง่ายๆ แต่เป็นส่วนพื้นฐานของ PowerShell คุณจะพบว่าตัวเองใช้สิ่งนี้หลายครั้งในเกือบทุกสคริปต์ที่คุณเขียน ฉันหวังว่าคุณจะมีความเข้าใจที่ดีขึ้นกว่าเดิม

บทความที่เกี่ยวข้อง