use*_*279 4 syntax powershell command-line parsing parameter-passing
我有以下代码:
$srv_range = 29..30+40+50..52
$srv_range.GetType()
$NewVMTemplate = New-Object psobject
$NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null
$srv_range | % {
$pod= $_
$servers = @()
1..2 | % {
$server = $NewVMTemplate | Select-Object *
$server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_
$servers += $server
}
ForEach ( $server in $servers) {
write-host $server.Name
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
PowerCLI C:\ .\eraseme.ps1
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
pod29-srv1
pod29-srv2
pod30-srv1
pod30-srv2
pod40-srv1
pod40-srv2
pod50-srv1
pod50-srv2
pod51-srv1
pod51-srv2
pod52-srv1
pod52-srv2
Run Code Online (Sandbox Code Playgroud)
我想从CLI输入范围,但是我使用此代码获得以下输出
param(
[Parameter(Mandatory=$False)] $srv_range
)
#$srv_range = 29..30+40+50..52
$srv_range.GetType()
$NewVMTemplate = New-Object psobject
$NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null
$srv_range | % {
$pod= $_
$servers = @()
1..2 | % {
$server = $NewVMTemplate | Select-Object *
$server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_
$servers += $server
}
ForEach ( $server in $servers) {
write-host $server.Name
}
}
PowerCLI C:\ .\eraseme.ps1 29..30+40+50..52
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
pod29..30+40+50..52-srv1
pod29..30+40+50..52-srv2
Run Code Online (Sandbox Code Playgroud)
如何从CLI输入范围并获得与第一个代码相同的结果?
mkl*_*nt0 11
您的问题是在您的调用中将参数29..30+40+50..52视为字符串文字.\eraseme.ps1 29..30+40+50..52 - 它不会被识别为表达式.
要强制识别为表达式,只需将参数括在(...):
.\eraseme.ps1 (29..30+40+50..52)
Run Code Online (Sandbox Code Playgroud)
请注意,通过使用更具体的类型声明参数,可以使脚本更加健壮,在这种情况下,尝试使用字符串调用它会立即失败:
[Parameter(Mandatory=$False)] [int[]] $srv_range
Run Code Online (Sandbox Code Playgroud)
(其他优化也可以应用于您的脚本.)
至于何时将不带引号的参数视为表达式与(可扩展)字符串(在参数模式下):
(...),$(...)并@(...)创建一个新的解析上下文,其中可以使用表达式甚至嵌套命令:
(...)足以表达单个表达式.$(...)(子表达式运算符)可以包含多个表达式/命令; 也可以@()(数组子表达式运算符),但它还确保其输出始终被视为数组.
值得注意的是,如果没有以上某种情况,则无法识别以下表达式:
[...] (类型引用)如 [Environment]::Version.. (范围表达式)如 1..10A (...)后跟包含参数值的集合或散列表的变量(例如$(...))的名称启动参数splatting.
@(...)可用于传递哈希表文字(例如$(...)).
它们本身可以按原样使用变量引用,包括索引/属性访问,甚至方法调用:
就其本身而言,令牌等"...",(...)以及@(...) 被认可,并返回其固有的类型.你甚至可以用这种方式调用方法(例如@).
如果直接在变量引用或方法调用之前添加或附加字符,则规则会更改 - 请参阅下文.
其他一切被视为可扩展字符串,即,类似的双引号字符串的内容,除了该元字符[1]仍然需要转义和某些令牌被解释为多个参数.
可扩展意味着嵌入的简单变量引用(例如,(...)或@)被内插(用其字符串化值替换).
请注意,这可能会导致表示与控制台中显示的给定值的默认输出格式不同(再次,请参阅此答案以获取更多信息).
@params如有必要,将变量名称括在其中以便与后续字符消除歧义(例如,@{ ... }).要访问变量值的属性或使用索引或调用方法或嵌入任意命令,必须将表达式括在@{ key = 'value' },例如,{ ... }
通常,最安全的是使用嵌入的变量引用/表达式来包含标记[scriptblock],因为它避免了以下边缘情况:
$HOME在未加引号的标记的开头不会被解释为可扩展字符串的一部分,它被视为一个单独的参数(例如,$PSVersionTable.PSVersion产生两个参数:结果$someArray[0]和文字$someString.ToUpper()).$HOME在令牌的开头紧接着是一个简单的变量引用或子表达式,也会导致单独的参数.$foo.Length-more结果有两个参数:文字$foo.Length和值-more)注意:即使扩展的结果是字符串,它也不一定是一个:最终类型由扩展值绑定的手头命令参数的类型决定.
逃避/引用:
PowerShell有许多元字符$HOME\Desktop,并且一个值得注意的缺陷是$env:APPDATA\Test必须将其转义为文字处理,因为{...}PowerShell的数组构造运算符.
要转义单个字符,请在其${HOME}前面加上(反引号).
为避免单独转义元字符的需要,请将值括在$(...)(双引号)或v$($PSVersionTable.PSVersion)(单引号)中:
如果希望对字符串进行插值(展开),即希望能够嵌入变量引用和子表达式,请使用双引号.
"..."- 以下字符.将它们视为文字: $(...)使用单引号将值视为文字.
Write-Output $('ab')c as$('ab')单引号或双引号通常是逃避值中空格的最简单方法.
最后,请注意,c所谓的停止解析符号(PSv3 +)完全改变了对所有剩余参数的解释:设计用于遗留.命令行,它会停止解释除了.$HOME样式.环境变量的扩展之外的其余部分.看到$HOME
[1] 参数模式元字符(具有特殊句法意义的字符)是:
cmd.exe.
其中,,仅在令牌的开头是特殊的.
例子
Write-Output 1..10 # STRING: -> '1..10'
Write-Output (1..10) # EXPRESSION: -> @(1, 2, ...)
# Write-Output $(1..10) would work too, but is only necessary if
# the enclosed expression comprises *multiple* statements.
Write-Output [Environment]::Version # STRING: -> '[Environment]::Ticks'
Write-Output ([Environment]::Version) # EXPRESSION: -> a [System.Version] instance.
Write-Output a,b # !! ARRAY @(1, 2), because "," is not escaped.
Write-Output a`,b #`# STRING 'ab'
Write-Output "a,b" # ditto
Write-Output 'a,b' # ditto
Write-Output $HOME\Desktop # EXPANDED string (e.g.) 'C:\Users\jdoe\Desktop'
Write-Output "$HOME\Desktop" # ditto
Write-Output '$HOME\Desktop' # LITERAL string '$HOME\Desktop'
Write-Output dir=$HOME # EXPANDED string (e.g.) 'dir=C:\Users\jdoe\Desktop'
Write-Output $PSVersionTable.PSVersion # a [System.Version] instance
Write-Output "$($PSVersionTable.PSVersion)/more" # a [string]; e.g., '5.1.14393.576/more'
Write-Output "v$($PSVersionTable.PSVersion)" # ditto; e.g., 'v5.1.14393.576'
# !!! These DO NOT WORK as intended.
Write-Output $($PSVersionTable.PSVersion)/more # $(...) at the *start*
Write-Output $PSVersionTable.PSVersion/more # $(...) missing
Write-Output "$PSVersionTable.PSVersion/more" # $(...) missing
Write-Output .$HOME # Specifically, .$ at the beginning is the problem; escaping . works
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
709 次 |
| 最近记录: |