我试图弄清楚如何将多个字符串作为数组传递给 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 函数。
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
为了补充Martin Brandl 的有用、中肯的回答,并提供一些背景信息:
$args
是自动变量的一个实例,表示其值由 PowerShell 本身控制的特殊变量。
因此,您应该避免自定义使用自动变量,即使在它碰巧起作用的情况下(见下文)。
理想情况下,PowerShell 本身会始终如一地阻止这种自定义使用(它只对一些自动变量这样做),并且在 GitHub 上存在关于强制执行的辩论,但出于向后兼容性的原因最终决定不这样做。
相反,现在正在通过PSScriptAnalyzer发出关于在安装了PowerShell 扩展的Visual Studio Code中分配给自动变量的设计时警告。
不幸的是,如果没有 Visual Code 的帮助,您通常无法从变量名中推断出变量名是否指代自动变量,并且也没有发现它们的编程方式——阅读帮助主题是唯一的选择;见下一节。
笔记:
该列表是使用以下命令生成的,从Windows PowerShell v5.1 开始 - 在 PowerShell Core中,该列表更短,因为删除了一些过时的变量。
该命令依赖于相关帮助主题的字符串解析;这种方法很脆弱,但它是目前发现自动变量的唯一方法,因为没有基于反射的方法。
这个 GitHub 问题建议实现编程可发现性,并讨论为自动变量引入单独的保留命名空间的可能性。
随着时间的推移,可以引入新的自动变量;如果合适的话,希望它们的只读状态将在引入时强制执行。
一些自动变量是合法可写的:
$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
.