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

PowerShell สำหรับผู้คน: ทำให้เชลล์ทำงานเพื่อคุณ


นามแฝงเป็นเพียงทางเลือกชื่อคำสั่งสั้นๆ แทนที่จะพิมพ์ Get-Process คุณสามารถพิมพ์ ps ได้ แม้ว่าฉันจะไม่สามารถทำมันพังได้ การใช้นามแฝงที่พรอมต์คำสั่งเป็นวิธีที่ดีในการเร่งงานของคุณและลดการพิมพ์ผิด แม้ว่าฉันจะไม่พิมพ์สิ่งนี้ลงในสคริปต์:

gsv | ? status -eq running

เมื่อได้รับแจ้งก็รวดเร็วและได้ผลลัพธ์ที่ต้องการ อย่างไรก็ตาม คุณไม่สามารถสร้างนามแฝงสำหรับคำสั่งและพารามิเตอร์ของคำสั่งได้ ตัวอย่างเช่น ฉันชอบพารามิเตอร์ -First และ -Last ที่มี Select-Object แต่ฉันไม่สามารถสร้างนามแฝงที่เทียบเท่ากับ Select-Object -last 10 ได้ อย่างไรก็ตาม สิ่งที่คุณ ทำได้ ทำได้คือสร้าง wrapper ของคุณเองรอบๆ คำสั่งและใส่นามแฝงลงไป นี่คือฟังก์ชันที่ฉันเขียนสำหรับ Select-Object -Last X

#requires -version 3.0 

Function Select-Last {

<#
.Synopsis
Select last X number of objects
.Description
This command takes pipelined input and selects the last specified number of objects which are then written to the pipeline.

There is a trade off of convenience for performance. For a very large number processed objects, use Select-Object directly
.Example
PS C:\> dir c:\scripts\*.ps1  | sort lastwritetime | last 5
.Notes
Last Updated: 8/25/2014
Version     : 0.9

.Link
Select-Object
#>

[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory,HelpMessage="How many objects do you want to get?")]
[ValidateScript({$_ -gt 0})]
[int]$Last,
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[object]$InputObject
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
    Write-Verbose -Message "Selecting last $Last objects"

    #initialize an array to hold all incoming objects
    $data=@()
    #initialize a counter
    $total=0
    #track when the command started in order to calculate how long the command took to complete.
    $start=Get-Date
} #begin

Process {
    $total++
    if ($total -le $Last) {
        #add each piped object to temporary array
        $data+=$InputObject
    }
    else {
      #move all items in the array up one
      $data = $data[1..$Last]
      #add the new item
      $data+=$InputObject
    }
} #process

End {
    #write the results
    $data
    $end = Get-Date
    Write-Verbose -Message "Processed $total items in $($end-$start)"
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
} #end
}

Set-Alias -Name Last -Value Select-Last

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

dir c:\work\*.txt | sort lastwritetime | last 5

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

โปรดทราบว่าอาจมีข้อเสียระหว่างความสะดวกและประสิทธิภาพ คำสั่งนี้ใช้นามแฝงและฟังก์ชันที่กำหนดเองของฉัน:

Measure-command {1..5000 | last 3}

ใช้เวลา 237ms ในขณะที่แนวทาง Select-Object:

Measure-command {1..5000 | select -Last 3}

ใช้เวลาเพียง 49ms แต่ฉันพนันได้เลยว่าคุณอาจยินดีที่จะยอมรับการแลกเปลี่ยนนั้นเพื่อบันทึกการพิมพ์บางส่วน แน่นอนว่าหากมีคำสั่ง Last ก็ควรมีคำสั่ง First

Function Select-First {
<#
.Synopsis
Select first X number of objects
.Description
This command takes pipelined input and selects the first specified number of objects which are then written to the pipeline.
.Example
PS C:\> get-process | sort WS -descending | first 5
.Notes
Last Updated: 8/25/2014
Version     : 0.9

.Link
Select-Object
#>
[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory,HelpMessage="How many objects do you want to get?")]
[ValidateScript({$_ -gt 0})]
[int]$First,
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[object]$InputObject
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
    Write-Verbose -Message "Selecting first $First objects"
    #track when the command started in order to calculate how long the command took to complete.
    $start=Get-Date
    #initialize a counter
    $i=0
} #begin

Process {
    #add each piped object to temporary array
    $i++
   
    if ($i -le $First) {    
        $InputObject
    }
    else {
        #we're done here
        Write-Verbose "Limit reached"
        $end = Get-Date
        Write-Verbose -Message "Processed $($data.count) items in $($end-$start)"
        Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
        #bail out
        break
    }
} #process

End {
    #not used    
} #end
}

Set-Alias -Name First -Value Select-First

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

ps | sort ws -des | first 3

ในตัวอย่างนี้ ฉันไม่เพียงใช้ประโยชน์จากนามแฝงเท่านั้น แต่ยังรวมถึงพารามิเตอร์ตำแหน่งด้วย และต้องพิมพ์ชื่อพารามิเตอร์ให้เพียงพอเท่านั้น เพื่อให้ PowerShell รู้ว่าฉันต้องการอะไร

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

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