Powershell 调用操作符 9


调用操作符“&”虽然简短,但是给我们执行Powershell命令提供了很大的方便。如果你之前将Powershell命令存储在了一个字符串中,或者一个变量中。此时,调用操作符就可以将字符串直接解释成命令并执行,如果在Powershell控制台中,你只须要输入即可。具体,如下:

#将命令存储在变量中:
$command = "Dir"
# 如果直接输出变量,字符串原样输出。
$command

#Dir

#如果使用调用操作符"&"
& $command

    目录: E:

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          2012/5/9      0:42            Blog
d----         2012/5/23     21:45            DooMLoRD_v3_ROOT-zergRush-busybox-
                                             su
d----          2012/6/1     20:21            Haitch-TFS
d----         2012/3/25     15:32            KillProcess

调用操作符只能接受单个命令

但是调用操作符不能接受全部的Powershell脚本或命令,只能接受单个的一条命令,例如使用:

$command = "Dir $env:windir"
& $command
就会报错
无法将“Dir C:windows”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后重试。
所在位置 E:MyScript.ps1:6 字符: 2
+ & <<<<  $command
    + CategoryInfo          : ObjectNotFound: (Dir C:windows:String) [], Comm
   andNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

为什么会这样呢?追根溯源,Powershell中的调用符,首先会使用get-command去发现命令是否可用,而get-command的确只支持单独的一条命令,不支持命令串或者脚本串。 调用操作符执行CommandInfo对象 调用操作符初始化时会将指定的文本传递给get-command,然后有get-command去检索命令,事实上,调用操作符甚至可以直接执行一个CommandInfo对象,绕过自身的内部get-command,例如:

PS E:> $command=Get-Command tasklist
PS E:> $command

CommandType     Name
-----------     ----
Application     tasklist.exe

PS E:> & $command

映像名称                       PID 会话名              会话#       内存使用
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0         24 K
System                           4 Services                   0        560 K
smss.exe                       356 Services                   0        756 K
csrss.exe                      564 Services                   0      3,744 K
csrss.exe                      680 Console                    1     71,512 K
wininit.exe                    688 Services                   0      2,904 K
services.exe                   740 Services                   0      8,552 K
lsass.exe                      764 Services                   0     10,676 K
lsm.exe                        776 Services                   0      3,240 K

通过命令名称唯一标识一条命令

但是可能存在别名,命令,函数的的名称一样,那Powershell会不会纠结到底执行哪个呢?当然不会,因为它们之间是有一个优先级的。从高到底,依次为:

Alias(1)
Function(2)
Filter(2)
Cmdlet(3)
Application(4)
ExternalScript(5)
Script (-)

下面举个例子:

PS E:> function Ping(){"我是Ping函数"}
PS E:> Set-Alias -Name Ping -Value echo

CommandType Name     Definition
----------- ----     ----------
Alias       Ping     echo
Function    Ping     param()...
Application PING.EXE C:windowsSYSTEM32PING.EXE

PS E:> ping "测试我的Ping,估计执行的别名echo"
测试我的Ping,估计执行的别名echo

PS E:> del Alias:Ping
PS E:> ping ; #别名已经被删除,估计执行的是函数PING
我是Ping函数

PS E:> del Function:Ping
PS E:> ping baidu.com ; #函数已经被删除,估计执行的是函数ping 程序

正在 Ping baidu.com [220.181.111.85] 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
请求超时。

220.181.111.85 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),

那怎样突破优先级的限制执行指定的命令呢?方法都是大同小异,通过特定信息过滤到指定的CommandInfo对象,然后直接使用我们本篇的调用操作符。例如当存在如下的命令Ping命令

CommandType     Name
-----------     ----
Alias           Ping
Function        Ping
Application     PING.EXE

我想调用第三个,可以使用:
PS E:> $command=Get-Command -Name ping | where {$_.CommandType -eq "Application" }
PS E:> & $command

用法: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
           [-r count] [-s count] [[-j host-list] | [-k host-list]]
           [-w timeout] [-R] [-S srcaddr] [-4] [-6] target_name

选项:
    -t             Ping 指定的主机,直到停止。
                   若要查看统计信息并继续操作 - 请键入 Control-Break;
                   若要停止 - 请键入 Control-C。
    -a             将地址解析成主机名。
    -n count       要发送的回显请求数。
    -l size        发送缓冲区大小。
    -f             在数据包中设置“不分段”标志(仅适用于 IPv4)。
    -i TTL         生存时间。
    -v TOS         服务类型(仅适用于 IPv4。该设置已不赞成使用,且
                   对 IP 标头中的服务字段类型没有任何影响)。
    -r count       记录计数跃点的路由(仅适用于 IPv4)。
    -s count       计数跃点的时间戳(仅适用于 IPv4)。
    -j host-list   与主机列表一起的松散源路由(仅适用于 IPv4)。
    -k host-list   与主机列表一起的严格源路由(仅适用于 IPv4)。
    -w timeout     等待每次回复的超时时间(毫秒)。
    -R             同样使用路由标头测试反向路由(仅适用于 IPv6)。
    -S srcaddr     要使用的源地址。
    -4             强制使用 IPv4。
    -6             强制使用 IPv6。

#或者& (Get-Command -Name ping)[2]
×用微信扫描并分享
本文链接: https://www.pstips.net/powershell-call-operator.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

9 条评论 “Powershell 调用操作符