当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 关于 PS 项目

作者:精品下载站 日期:2024-12-14 02:19:53 浏览:15 分类:玩电脑

关于 PS 项目


简短描述

包含管道对象中当前对象的自动变量。

详细描述

PowerShell 包含 $PSItem 变量及其别名 $_ 作为处理当前对象(例如在管道中)的脚本块中的自动变量。本文在示例中使用 $PSItem,但每个示例中的 $PSItem 都可以替换为 $_

您可以在对管道中的每个对象执行操作的命令中使用此变量。

$PSItem 有一些常见用例:

  • ForEach-Objectcmdlet 的 Process 参数的脚本块中
  • Where-Object cmdlet 的 FilterScript 参数的脚本块中
  • 在内部方法 ForEachWhere
  • 使用延迟绑定脚本块参数
  • switch 语句的条件值和关联的脚本块中
  • 在函数的 process 块中
  • filter 定义中
  • ValidateScript 属性的脚本块中
  • -replace 运算符的替换操作数脚本块中

本文的其余部分包括针对这些用例使用 $PSItem 的示例。

ForEach-对象过程

ForEach-Object cmdlet 设计用于对管道中的对象进行操作,为管道中的每个对象执行一次 Process 参数的脚本块。

您可以在 Process 参数的脚本块中使用 $PSItem,但不能在 BeginEnd 参数脚本块中使用。如果您在 BeginEnd 参数脚本块中引用 $PSItem,则该值为 $null,因为这些脚本块不不要对管道中的每个对象进行操作。

$parameters = @{
    Begin   = { Write-Host "PSItem in Begin is: $PSItem" }
    Process = {
        Write-Host "PSItem in Process is: $PSItem"
        $PSItem + 1
    }
    End     = { Write-Host "PSItem in End is: $PSItem" }
}

$result = 1, 2, 3 | ForEach-Object @parameters

Write-Host "Result is: $result"
PSItem in Begin is:
PSItem in Process is: 1
PSItem in Process is: 2
PSItem in Process is: 3
PSItem in End is:
Result is: 2 3 4

Where-对象过滤器脚本

Where-Object cmdlet 旨在过滤管道中的对象。

您可以在 FilterScript 参数的脚本块中使用 $PSItem,该参数对管道中的每个输入对象执行一次。

1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2

在此示例中,FilterScript 检查当前对象是否为偶数,过滤掉任何奇数值,并仅从原始列表中返回 2

ForEach 和Where 方法

数组的 ForEach 和Where 内在方法都采用脚本块作为输入参数。您可以在这些脚本块中使用 $PSItem 来访问当前对象。

@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B

在此示例中,ForEach 方法的脚本块将当前对象大写。然后 Where 方法的脚本块仅返回 B

延迟绑定脚本块参数

延迟绑定脚本块允许您在执行管道 cmdlet 之前使用 $PSItem 定义其参数。

dir config.log | Rename-Item -NewName { "old_$($_.Name)" }

Switch 语句脚本块

在 switch 语句中,您可以在操作脚本块和语句条件脚本块中使用 $PSItem

$numbers = 1, 2, 3

switch ($numbers) {
    { ($PSItem % 2) -eq 0 } { "$PSItem is even" }
    default { "$PSItem is odd" }
}
1 is odd
2 is even
3 is odd

在此示例中,语句条件脚本块检查当前对象是否为偶数。如果是偶数,则关联的操作脚本块会输出一条消息,指示当前对象是偶数。

default 条件的操作脚本块输出一条消息,指示当前对象是奇数。

功能过程块

定义函数时,可以在 process 块定义中使用 $PSItem,但不能在 beginend 中使用> 块定义。如果您在 beginend 块中引用 $PSItem,则该值为 $null,因为这些块不t 对管道中的每个对象进行操作。

当您在 process 块定义中使用 $PSItem 时,如果在管道中调用该函数,则该值为当前对象,否则 $null

function Add-One {
    process { $PSItem + 1 }
}

1, 2, 3 | Add-One
2
3
4

有用的提示

虽然您可以在高级函数中使用 $PSItem,但没有理由这样做。如果您打算从管道接收输入,最好使用 Parameter 属性的 ValueFromPipeline* 参数之一定义参数。

使用高级函数的参数属性和 cmdlet 绑定使得实现比处理当前对象以获取所需值更加明确和可预测。

在高级函数中 $PSItem 的一个很好的用途是,当函数具有多个从管道获取输入的参数时,检查当前对象本身以进行调试或记录。

function Write-JsonLog {
    [CmdletBinding()]
    param(
        [parameter(ValueFromPipelineByPropertyName)]
        [string]$Message
    )
    begin {
        $entries = @()
    }
    process {
        $entries += [pscustomobject]@{
            Message   = $Message
            TimeStamp = [datetime]::Now
        }

        if ($PSItem) {
            $props  = $PSItem | ConvertTo-Json
            $number = $entries.Length
            Write-Verbose "Input object $number is:`n$props"
        }
    }
    end {
        ConvertTo-Json -InputObject $entries
    }
}

此示例函数输出带有消息和时间戳的 JSON 对象数组。当在管道中调用时,它对每个条目使用当前对象的 Message 属性。它还将当前对象本身的 JSON 表示形式写入详细流,以便您可以看到与输出日志相比的实际输入。

$Items = @(
    [pscustomobject]@{
        Name    = 'First Item'
        Message = 'A simple note'
    }
    [pscustomobject]@{
        Name    = 'Item with extra properties'
        Message = 'Missing message, has info instead'
        Info    = 'Some metadata'
        Source  = 'Where this came from'
    }
    [pscustomobject]@{
        Name    = 'Last Item'
        Message = 'This also gets logged'
    }
)

$Items | Write-JsonLog -Verbose
VERBOSE: Input object 1 is:
{
    "Name":  "First Item",
    "Message":  "A simple note"
}
VERBOSE: Input object 2 is:
{
    "Name":  "Item with extra properties",
    "Message":  "Missing message, has info instead",
    "Info":  "Some metadata",
    "Source":  "Where this came from"
}
VERBOSE: Input object 3 is:
{
    "Name":  "Last Item",
    "Message":  "This also gets logged"
}
[
    {
        "Message":  "A simple note",
        "TimeStamp":  "\/Date(1670344068257)\/"
    },
    {
        "Message":  "Missing message, has info instead",
        "TimeStamp":  "\/Date(1670344068259)\/"
    },
    {
        "Message":  "This also gets logged",
        "TimeStamp":  "\/Date(1670344068261)\/"
    }
]

过滤器定义

您可以在过滤器定义的语句列表中使用 $PSItem

当您在 filter 定义中使用 $PSItem 时,如果在管道中调用过滤器,则该值为当前对象,否则为 $null

filter Test-IsEven { ($PSItem % 2) -eq 0 }

1, 2, 3 | Test-IsEven
False
True
False

在此示例中,如果当前对象是偶数,则 Test-IsEven 过滤器输出 $true;如果不是,则输出 $false

ValidateScript 属性脚本块

您可以在 ValidateScript 属性的脚本块中使用 $PSItem。与 ValidateScript 一起使用时,$PSItem 是当前正在验证的对象的值。当变量或参数值是数组时,将为数组中的每个对象调用一次脚本块,并将 $PSItem 作为当前对象。

function Add-EvenNumber {
    param(
        [ValidateScript({ 0 -eq ($PSItem % 2) })]
        [int[]]$Number
    )

    begin {
        [int]$total = 0
    }

    process {
        foreach ($n in $Number) {
            $total += $n
        }
    }

    end {
        $total
    }
}

Add-EvenNumber -Number 2, 4, 6

Add-EvenNumber -Number 1, 2
12

Add-EvenNumber:
Line |
  24 |  Add-EvenNumber -Number 1, 2
     |                         ~~~~
     | Cannot validate argument on parameter 'Number'. The
" 0 -eq ($PSItem % 2) " validation script for the argument
with value "1" did not return a result of True. Determine
why the validation script failed, and then try the command
again.

在此示例中,ValidateScript 属性的脚本块针对传递给 Number 参数的每个值运行一次,如果任何值不偶数,则返回错误。

Add-EvenNumber 函数将有效的输入数字相加并返回总数。

-replace 运算符的替换脚本块

从 PowerShell 6 开始,您可以在调用替换运算符并定义替换脚本块时使用 $PSItem。当您这样做时,$PSItem 的值就是当前匹配的值。

$datePattern = '\d{4}-\d{2}-\d{2}'
'Today is 1999-12-31' -replace $datePattern, { [datetime]$PSItem.Value }
Today is 12/31/1999 00:00:00

在此示例中,替换脚本块通过将值转换为日期时间,将原始日期字符串替换为当前区域性的默认格式。

参见

  • about_Arrays
  • about_automatic_variables
  • about_比较_运算符
  • 关于函数
  • about_Script_Blocks
  • about_Switch
  • ForEach-Object
  • Where-Object

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯