如何在PowerShell中处理命令行参数

608

如何最好地处理命令行参数?

似乎有几种方法被认为是“最好”的,因此我不知道该如何处理像这样简单的东西:

script.ps1 /n name /d domain

script.ps1 /d domain /n name.

有没有可以更好地处理这个问题的插件?我知道我在重新发明轮子。

显然,我已经拥有的东西并不漂亮,肯定也不是“最好的”,但它能够工作…只是丑陋了一点。

for ( $i = 0; $i -lt $args.count; $i++ ) {
    if ($args[ $i ] -eq "/n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "/d"){ $strDomain=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-d"){ $strDomain=$args[ $i+1 ]}
}
Write-Host $strName
Write-Host $strDomain
1个回答

1135

你正在重复造轮子。普通的PowerShell脚本参数以-开头,例如:script.ps1 -server http://devserver

然后在param部分处理它们(请注意,这必须从您脚本中的第一行非注释行开始)。

您还可以为参数分配默认值,如果参数不可用则从控制台读取它们或停止脚本执行:

 param (
    [string]$server = "http://defaultserver",
    [Parameter(Mandatory=$true)][string]$username,
    [string]$password = $( Read-Host "Input password, please" )
 )

在脚本中,您可以简单地

write-output $server

由于所有参数都成为脚本范围内可用的变量,因此可以使用默认值初始化变量。

在此示例中,如果在调用脚本时未传递$server参数,则$server将获取默认值,如果省略-username参数,则脚本停止运行,并提示输入终端密码,如果省略-password参数,则会要求终端输入。

更新: 您可能还想将“标志”(布尔型的真/假参数)传递给PowerShell脚本。例如,当不使用force选项时,您的脚本可以接受一个“force”标志,脚本以更谨慎的方式运行。 这种情况下,关键字是[switch]参数类型:

 param (
    [string]$server = "http://defaultserver",
    [string]$password = $( Read-Host "Input password, please" ),
    [switch]$force = $false
 )

在脚本中,您可以像这样使用它:

if ($force) {
  //deletes a file or does something "bad"
}

现在,调用脚本时,您需要这样设置开关/标记参数:

.\yourscript.ps1 -server "http://otherserver" -force

如果您明确希望声明该标志未设置,则有一种特殊的语法可以使用。

.\yourscript.ps1 -server "http://otherserver" -force:$false

以下是与 PowerShell 5.0 相关的微软文档链接(也提供版本 3.0 和 4.0 的文档链接):


82
PowerShell的一个重要优势之一是提供了一个标准参数解析基础设施,易于使用。 - Keith Hill
15
在PowerShell 2.0中,为了指定必需的参数有一种语法:[Parameter(Mandatory=$true)][string]$username,取代了[string]$username = $(throw "-username is required.")。这两种技术的差异可以在此链接中找到更多信息:http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/use-powershell-to-make-mandatory-parameters.aspx。 - v.karbovnichy
10
当没有提供参数时要注意 bug,PowerShell 会从命令行中获取任何额外的文本: .\yourscript.ps1 -server "http://serv" -password "mypass" typo 这将神奇地将 'typo' 分配给 $username。 - sheamus
9
@sheamus:那不是一个 Bug!PowerShell 会按照他们给出的顺序处理并赋值参数,除非使用正确的参数名称进行覆盖。例如,如果你的参数块列出了 $user、$pass 和 $server,并且你执行 yourscript.ps1 a b c,则 a 将被设置为 $user,b 将被设置为 $pass,c 将被设置为 $server,除非你专门指定它们!因此,如果你说:yourscript.ps1 -pass a b c,$pass 将被设置为 a,并且剩余的(未命名)参数将用于填充缺失的参数,按照参数块中列出的顺序进行,所以 $user = b,$server = c。 - Fernando Madruga
6
为避免“打字错误”场景,一种方法是明确否认参数位置绑定,可以对每个参数或全局设置。只需在你的 cmdlet 顶部添加 [CmdletBinding(PositionalBinding=$false)] 即可。 - Justin
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接