您的问题是参数 29..30+40+50..52 在您的 .\eraseme.ps1 29..30+40+50..52 调用中被视为 字符串文字 - 它不被识别为 表达式.
要强制识别为表达式,请将参数括在(...)中,grouping operator:
.\eraseme.ps1 (29..30+40+50..52)
同样适用,如果您想使用(另一个)命令的输出作为命令参数;例如:
# Pass the lines read from file paths.txt as an array to Get-ChildItem
# (Parameter -Path is implied in both commands).
Get-ChildItem (Get-Content paths.txt)
两旁:
• $(...),subexpression operator,只有在两种情况下才需要:(a) 将整个语句,特别是循环和条件语句,嵌入到另一个语句中,以及 (b)在 "..." 中嵌入表达式、命令或语句,这是一个可扩展(插值)字符串。只需 (...) 就足以在语句中嵌入单个 command 或 expression(即使在 变量赋值的 RHS 上也不需要这样做 em>)。虽然不太可能,但不必要地使用 $(...) 可能会产生副作用 - 请参阅 this answer。
• 您可以使您的脚本更健壮,方法是使用更具体的类型声明参数,在这种情况下,尝试使用字符串调用它会立即失败:
[Parameter(Mandatory=$False)] [int[]] $srv_range
(其他优化也可以应用于您的脚本。)
可选的背景信息
至于当一个 unquoted 标记被视为 表达式 或 嵌套命令 与 (可扩展) 参数模式中的字符串(另见:about_Parsing):
-
(...)、$(...) 和 @(...)它们自己或在令牌的开头创建一个新的解析上下文,其中可以使用表达式甚至嵌套命令:
-
(...) 对于单个 表达式或命令就足够了。 $(...)(子表达式运算符)可以包含多个表达式/命令; @()(array 子表达式运算符)也可以,并且它还确保其输出始终被视为 array。
-
值得注意的是,如果不包含在上述任一表达式中,则无法识别以下表达式:
-
[...](类型文字)和对其成员的访问,例如[Environment]::Version
-
..(范围表达式)如1..10
-
如果在 标记的开头、(...)、$(...) 或 @(...) 后面跟着附加字符,则第一个附加字符被视为 的开始新的、单独的论点。
-
相比之下,如果它们之前有一个不带引号的文字或一个仅变量引用,$(...) 的工作方式类似于 @ 内部987654352@(可扩展的字符串),(...) 开始一个作为表达式的 新参数,@(...) 被视为文字 @ 和 (...) 再次开始一个新参数,它是表达。
-
@ 后跟 变量的名称(例如,@params)包含参数值的集合或哈希表启动 parameter splatting。
-
@{ ... } 可用于传递 散列表文字(例如,@{ key = 'value' })。
-
{ ... } 创建一个脚本块 ([scriptblock])。
-
自行或在记号开头,变量引用,包括成员访问(属性访问、方法调用、索引)可以按原样使用:
-
$HOME、$PSVersionTable.PSVersion、$someArray[0] 和 $someString.ToUpper() 等表达式被识别,并作为其固有类型返回。
-
如果没有成员访问,即使用简单的变量引用(例如$HOME),后续字符(可能)被视为相同参数的一部分,然后被解释作为可扩展字符串 - 见下文。
-
使用成员访问,任何附加字符中的第一个被视为新参数的开始(例如,$foo.Length-more 导致两个 参数:$foo.Length 的值和字符串字面量-more)。
-
其他所有内容都被视为可扩展字符串,即,类似于双引号字符串的内容,除了 元字符[1] 仍然需要转义 并且某些标记被解释为多个 参数。
-
可扩展意味着嵌入的简单变量引用(例如,$HOME\Desktop 或$env:APPDATA\Test)被插值(替换为它们的字符串化值) )。
请注意,这可能会导致表示不同于控制台中显示的给定值的默认输出格式,例如(再次,请参阅this answer 了解更多信息)。
- 如有必要,请在
{...} 中包含变量名称以消除其与后续字符的歧义(例如,${HOME})。
-
访问变量值的属性或使用索引或调用方法或嵌入任意命令 em>,必须将表达式括在$(...)中,例如v$($PSVersionTable.PSVersion)
-
一般来说,在"..."中用嵌入的变量引用/表达式括起来是最安全的,因为它可以避免以下边缘情况:
* 开始处的$(...)被不解释为可扩展字符串的一部分,它被视为单独的参数(例如,Write-Output $('ab')c 导致 两个 参数:$('ab') 和文字 c 的结果)。
* . 在标记的开始紧跟一个简单的变量引用或子表达式也会导致单独的参数强>.
(例如,.$HOME 会产生 两个 参数:文字 . 和 $HOME 的值)
-
最后,请注意 --%,即所谓的 停止解析符号 (PSv3+),完全改变了所有剩余参数的解释:设计用于旧的cmd.exe 命令行,它停止解释该行的其余部分,除了cmd.exe-style %...% 环境变量的扩展。见Get-Help about_Parsing
至于使用引用标记:
[1] 参数模式元字符(具有特殊句法含义的字符)是:
<space> ' " ` , ; ( ) { } | & < > @ #。
其中,< > @ # 仅在令牌的开始处是特殊的。
示例
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