在 powershell 中制作 Alias 的最简单方法是什么?

What is the simplest way to make Alias in powershell?

我想知道是否有任何简单的方法可以像 cmd 一样为 powershell 创建别名。 例如:在 cmd 中,doskey art=php artisan $* 其中 $* 是可选的。目前,我在 powershell 中使用以下别名。

function runArtisanCommand
{
    param(
        [Parameter(Mandatory=$false, Position = 0, ValueFromRemainingArguments = $true)]
        $command
    )
    php artisan $command
}

Set-Alias art runArtisanCommand

这有点管用,但不带标志。例如:我不会写 art -hart route:list -c。在 art -h 命令中,它打印 php artisan 的输出并且根本不读取标志,但在 art route:list -c 命令中,它出错了。

runArtisanCommand : Missing an argument for parameter 'command'. Specify a parameter of type 'System.Object' and try again.
At line:1 char:16
+ art route:list -c
+                ~~
    + CategoryInfo          : InvalidArgument: (:) [runArtisanCommand], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,runArtisanCommand

我希望有比这更简单的解决方案。提前致谢。

传递未知参数的最简单和最方便的方法是 spatting automatic $args array - 作为 @args - 在 简单 函数或脚本 中(既不使用 [CmdletBinding()] 也不使用 [Parameter()]属性):

# Note: @args rather than $args makes the function work with named 
#       arguments for PowerShell commands too - see explanation below.
function runArtisanCommand { php artisan @args } 

# As in your question: Define alias 'art' for the function
# Note: Of course, you could directly name your *function* 'art'.
#       If you do want the function to have a longer name, consider one
#       that adheres to PowerShell's Verb-Noun naming convention, such as
#       'Invoke-ArtisanCommand'.
Set-Alias art runArtisanCommand

顺便说一句:由于目标可执行文件 php 既未 引用 也未根据 变量指定或expression,可以原样调用;否则,您将需要 &call operator - see 以获得背景信息。


至于你试过的:

问题是使用 -c 作为 直通 参数仅当您在其前面加上 --:

时才有效
# OK, thanks to '--'
art -- route:list -c

-- 告诉 PowerShell 将所有剩余参数视为 未命名(位置)参数,而不是尝试将 -c 等标记解释为 参数名称.

如果没有 ---c 将被解释为引用您的 -command 参数 (您声明为 $command 的参数ValueFromRemainingArguments = $true),假设 PowerShell 允许您指定名称 prefixes 来代替完整的参数名称,只要给定的前缀是明确的。

因为 [switch] 以外的任何类型的参数都需要关联的参数,-c(又名 -command)失败并显示一条错误消息。

您可以通过命名参数来避免冲突,这样它就不会与任何传递参数发生冲突,例如将其命名为-_args(带参数变量 $_args):

function runArtisanCommand
{
    param(
        # Note: `Mandatory = $false` and `Position = 0` are *implied*.
        [Parameter(ValueFromRemainingArguments)]
        $_args
    )
    php artisan @_args
}

但是,鉴于 使用 [Parameter()] 属性隐含地使您的函数成为 advanced function, it invariably also accepts common parameters,例如 -ErrorAction-OutVariable-Verbose... - 所有这些都可以通过明确的前缀/短别名传递;例如,-outv 代表 -OutVariable,或别名 -ea 代表 ErrorAction与他们的碰撞是不可避免的.

因此,-e still 等预期的传递参数将不起作用:

# FAILS, because -e ambiguously matches common parameters -ErrorAction 
# and -ErrorVariable.
PS> art router:list -e
Parameter cannot be processed because the parameter name 'e' is ambiguous.
Possible matches include: -ErrorAction -ErrorVariable.

同样,需要--

# OK, thanks to '--'
art -- router:list -e

总结:

  • 特别是函数包装对外部程序的调用,例如php.exe,使用simple function with @args,如顶部所示,不仅更简单,而且更健壮。

  • 对于 函数包装 PowerShell 命令(带有显式声明的参数):

    • 一个 简单的 函数与 @args 一起工作,
    • 但如果您还希望支持制表符完成显示syntax diagram with the supported parameters, by passing -?, or via Get-Help,请考虑定义一个(总是高级) 代理(包装)函数 通过 PowerShell SDK - 见下文。

可选背景信息:PowerShell 中的传递参数

作为 Mathias R. Jessen points out, the simplest way to pass (undeclared) arguments passed to a function or script through to another command is to use the automatic $args variable, which is an automatically populated array of all the arguments passed to a simple function or script (one that isn't advanced,通过使用 [CmdletBinding()] and/or [Parameter()] 属性)。

至于为什么要用@args而不是$args:

  • 在包装函数中按原样使用 $args 仅适用于传递 positional 参数(那些没有以参数名称为前缀的参数;例如, *.txt), 而不是 named 参数 (例如, -Path *.txt).

  • 如果最终目标命令是外部程序(例如本例中的php.exe),这不是问题,因为PowerShell 然后将 所有 参数视为位置参数(它无法知道目标程序的语法)。

  • 但是,如果最终调用 PowerShell 命令(带有正式声明的参数),则只有 splatting $args 数组 -这在语法上意味着我们 @args 相反 - 支持通过 named 参数传递。[1]

因此,作为一种习惯,我建议总是在简单的包装函数中使用 @args,它同样适用于外部程序。[ 2]

举一个简单的包装函数的例子 Get-ChildItem:

# Simple wrapper function for Get-ChildItem that lists recursively
# and by relative path only.
function dirTree {
  # Use @args to make sure that named arguments are properly passed through.
  Get-ChildItem -Recurse -Name @args 
}

# Invoke it with a *named* argument passed through to Get-ChildItem
# If $args rather than @args were used inside the function, this call would fail.
dirTree -Filter *.txt

使用代理函数进行更复杂的直通处理:

使用@args很方便,但代价是支持以下:

  • tab-completion,假设 tab-completion 仅适用于正式声明的参数(通常使用 param(...) 块)。

  • 显示 syntax diagram with the supported parameters, by passing -?, or via Get-Help

克服这些限制,最终目标命令的参数声明必须重复 在(然后是高级的)包装函数中;虽然这很麻烦,但 PowerShell 可以通过 PowerShell SDK 构建所谓的 代理(包装器)函数 来自动执行该过程 - 请参阅 .

注:

  • 关于常见的参数如-ErrorAction,是代理函数本身(自动)处理它们,但不应该'对来电者没有影响。

  • 脚手架代理函数仅适用于 PowerShell 命令,因为 PowerShell 不了解外部程序的语法。

    • 但是,您可以手动复制外部目标程序的参数声明。

[1] 请注意,自动 $args 数组具有支持此功能的内置魔法;使用 splatting 传递命名参数 not 支持自定义 array 并且需要使用 hash table 代替,如帮助中所述关于上面链接的 splatting 的主题。

[2]其实只有@args也支持--%的正确解释,stop-parsing symbol.