将参数作为数组传递给 PowerShell 函数
Passing arguments as array to PowerShell function
我正在尝试弄清楚如何将多个字符串作为数组传递给 powershell 函数。
function ArrayCount([string[]] $args) {
Write-Host $args.Count
}
ArrayCount "1" "2" "3"
ArrayCount "1","2","3"
ArrayCount @("1","2","3")
版画
2
0
0
如何将具有 3 个值的数组传递给 ArrayCount
函数?
为什么某些调用的计数为零?
在 PowerShell 中,$args 是一个自动变量,它引用未命名 参数。只需更改您的参数名称:
function ArrayCount([string[]] $myParam) {
Write-Host $myParam.Count
}
你会得到预期的输出:
1
3
3
编写于:PowerShell Core 7.0.0-preview.5 / Windows PowerShell v5.1
用一些背景信息来补充 :
$args
是 automatic variable 的一个实例,意思是一个特殊变量,其 值由PowerShell 本身.
因此,您应该避免自定义使用自动变量,即使它恰好起作用(见下文)。
理想情况下,PowerShell 本身会一致地 阻止这种自定义使用(它只对 一些 自动变量),debate on GitHub 关于强制执行,但出于向后兼容性的原因,最终决定不这样做。
相反,设计时警告现在正在发出关于 Visual Studio Code with the PowerShell extension installed, via PSScriptAnalyzer 中自动变量赋值的问题。
不幸的是,如果没有 Visual Code 的帮助,您通常无法推断变量名是否从其名称中引用自动变量 并且也没有 程序化 发现它们的方法 - 阅读帮助主题是唯一的选择;请参阅下一节。
不应可写的自动变量列表,但事实上是:
注:
从 Windows PowerShell v5.1 开始,使用以下命令生成列表 - 在 PowerShell Core,列表更短,因为删除了一些过时的变量。
该命令依赖于相关帮助主题的字符串解析;这种方法很脆弱,但它是目前发现自动变量的唯一方法,因为没有基于反射的方法。
This GitHub issue 建议实现程序化可发现性,还讨论了为自动变量引入 单独的保留命名空间 的可能性。
随着时间的推移,可能会引入新的自动变量;希望他们的只读状态(如果合适)将在引入时强制执行。
- 因为自动变量与用户变量共享一个命名空间,所以引入任何新的自动变量都有破坏现有代码的风险。
一个select几个自动变量合法可写:
$OFS
- 字符串化数组时使用的分隔符。
$null
- 特殊变量,它不仅在 读取 时表示空值,而且还设计为允许为其分配任何值,以便 丢弃它(不将它写入(成功)输出流)。
$LASTEXITCODE
,形式为 $global:LASTEXITCODE
,以设置要使用的进程退出代码(尽管最好使用 exit <n>
)。
下面列出的自动变量不是(例如$PID
)已经是有效读取-只有(因为他们应该)。 下面列出的那些 - 即意外可写的那些 - 属于以下类别:
那些总是悄悄丢弃分配的值(例如,$Input
,$MyInvocation
, $PSCmdlet
)
那些接受自定义值,但在自动分配值的上下文中覆盖(隐藏)它(例如,$args
,每当输入新的脚本块(函数/脚本)时,它都会自动设置为局部变量;您作为局部 参数 变量的使用实际上被忽略了)。
有混合案例,特别是$_
/ $PSItem
,其中分配的值在$_
会自动分配一个值,但在这样的上下文中,您 可以 (但不应该)分配一个新值(例如,'in' | ForEach-Object { $_ = $_ + '!'; $_ }
输出 in!
)
Name Predefined
---- ----------
_ False
AllNodes False
Args True
Event False
EventArgs False
EventSubscriber False
ForEach True
Input True
Matches True
MyInvocation True
NestedPromptLevel True
Profile True
PSBoundParameters True
PsCmdlet False
PSCommandPath True
PSDebugContext False
PSItem False
PSScriptRoot True
PSSenderInfo False
Pwd True
ReportErrorShowExceptionClass False
ReportErrorShowInnerException False
ReportErrorShowSource False
ReportErrorShowStackTrace False
Sender False
StackTrace True
This False
“预定义”是指它们默认是否存在于全局范围内。
以下代码用于检测它们 - 您可以预先设置 $VerbosePreference = 'Continue'
(并在之后重置)以查看已经只读的变量:
$autoVarNames = ((get-help about_automatic_variables) -split [environment]::newline -match '^\s*$\w+\s*$').Trim().Trim('$') | Sort-Object -Unique
foreach ($varName in $autoVarNames) {
$var = Get-Variable $varName -ErrorAction 'SilentlyContinue'
$exists = $?
if ($exists -and $var.Options -match 'readonly|constant') {
Write-Verbose "$varName`: read-only or constant"
} elseif ($varName -in 'NULL', 'OFS', 'LastExitCode') { # exceptions
Write-Verbose "$varName`: writable by design"
} else {
Set-Variable -Name $varName -Value $null -ErrorAction SilentlyContinue
if ($?) {
[pscustomobject] @{ Name = $varName; Predefined = $exists }
}
}
}
请注意,代码有一个硬编码的异常列表,以便不报告确实应该可写的自动变量,例如 $OFS
和 $LastExitCode
,或者可分配为安静空操作,例如 $null
.
我正在尝试弄清楚如何将多个字符串作为数组传递给 powershell 函数。
function ArrayCount([string[]] $args) {
Write-Host $args.Count
}
ArrayCount "1" "2" "3"
ArrayCount "1","2","3"
ArrayCount @("1","2","3")
版画
2
0
0
如何将具有 3 个值的数组传递给 ArrayCount
函数?
为什么某些调用的计数为零?
在 PowerShell 中,$args 是一个自动变量,它引用未命名 参数。只需更改您的参数名称:
function ArrayCount([string[]] $myParam) {
Write-Host $myParam.Count
}
你会得到预期的输出:
1
3
3
编写于:PowerShell Core 7.0.0-preview.5 / Windows PowerShell v5.1
用一些背景信息来补充
$args
是 automatic variable 的一个实例,意思是一个特殊变量,其 值由PowerShell 本身.
因此,您应该避免自定义使用自动变量,即使它恰好起作用(见下文)。
理想情况下,PowerShell 本身会一致地 阻止这种自定义使用(它只对 一些 自动变量),debate on GitHub 关于强制执行,但出于向后兼容性的原因,最终决定不这样做。
相反,设计时警告现在正在发出关于 Visual Studio Code with the PowerShell extension installed, via PSScriptAnalyzer 中自动变量赋值的问题。
不幸的是,如果没有 Visual Code 的帮助,您通常无法推断变量名是否从其名称中引用自动变量 并且也没有 程序化 发现它们的方法 - 阅读帮助主题是唯一的选择;请参阅下一节。
不应可写的自动变量列表,但事实上是:
注:
从 Windows PowerShell v5.1 开始,使用以下命令生成列表 - 在 PowerShell Core,列表更短,因为删除了一些过时的变量。
该命令依赖于相关帮助主题的字符串解析;这种方法很脆弱,但它是目前发现自动变量的唯一方法,因为没有基于反射的方法。
This GitHub issue 建议实现程序化可发现性,还讨论了为自动变量引入 单独的保留命名空间 的可能性。
随着时间的推移,可能会引入新的自动变量;希望他们的只读状态(如果合适)将在引入时强制执行。
- 因为自动变量与用户变量共享一个命名空间,所以引入任何新的自动变量都有破坏现有代码的风险。
一个select几个自动变量合法可写:
$OFS
- 字符串化数组时使用的分隔符。$null
- 特殊变量,它不仅在 读取 时表示空值,而且还设计为允许为其分配任何值,以便 丢弃它(不将它写入(成功)输出流)。$LASTEXITCODE
,形式为$global:LASTEXITCODE
,以设置要使用的进程退出代码(尽管最好使用exit <n>
)。
下面列出的自动变量不是(例如
$PID
)已经是有效读取-只有(因为他们应该)。 下面列出的那些 - 即意外可写的那些 - 属于以下类别:那些总是悄悄丢弃分配的值(例如,
$Input
,$MyInvocation
,$PSCmdlet
)那些接受自定义值,但在自动分配值的上下文中覆盖(隐藏)它(例如,
$args
,每当输入新的脚本块(函数/脚本)时,它都会自动设置为局部变量;您作为局部 参数 变量的使用实际上被忽略了)。有混合案例,特别是
$_
/$PSItem
,其中分配的值在$_
会自动分配一个值,但在这样的上下文中,您 可以 (但不应该)分配一个新值(例如,'in' | ForEach-Object { $_ = $_ + '!'; $_ }
输出in!
)
Name Predefined
---- ----------
_ False
AllNodes False
Args True
Event False
EventArgs False
EventSubscriber False
ForEach True
Input True
Matches True
MyInvocation True
NestedPromptLevel True
Profile True
PSBoundParameters True
PsCmdlet False
PSCommandPath True
PSDebugContext False
PSItem False
PSScriptRoot True
PSSenderInfo False
Pwd True
ReportErrorShowExceptionClass False
ReportErrorShowInnerException False
ReportErrorShowSource False
ReportErrorShowStackTrace False
Sender False
StackTrace True
This False
“预定义”是指它们默认是否存在于全局范围内。
以下代码用于检测它们 - 您可以预先设置 $VerbosePreference = 'Continue'
(并在之后重置)以查看已经只读的变量:
$autoVarNames = ((get-help about_automatic_variables) -split [environment]::newline -match '^\s*$\w+\s*$').Trim().Trim('$') | Sort-Object -Unique
foreach ($varName in $autoVarNames) {
$var = Get-Variable $varName -ErrorAction 'SilentlyContinue'
$exists = $?
if ($exists -and $var.Options -match 'readonly|constant') {
Write-Verbose "$varName`: read-only or constant"
} elseif ($varName -in 'NULL', 'OFS', 'LastExitCode') { # exceptions
Write-Verbose "$varName`: writable by design"
} else {
Set-Variable -Name $varName -Value $null -ErrorAction SilentlyContinue
if ($?) {
[pscustomobject] @{ Name = $varName; Predefined = $exists }
}
}
}
请注意,代码有一个硬编码的异常列表,以便不报告确实应该可写的自动变量,例如 $OFS
和 $LastExitCode
,或者可分配为安静空操作,例如 $null
.