PowerShell:上次执行结果是否有自动变量?
我正在寻找一个类似于Python交互式shell的“389;”变量的特性。在PowerShell中,我想要如下内容:PowerShell:上次执行结果是否有自动变量?,powershell,Powershell,我正在寻找一个类似于Python交互式shell的“389;”变量的特性。在PowerShell中,我想要如下内容: > Get-Something # this returns an object and display it to the output. # Now I want to assign that object to some variable > $anObj = ??? 不完全是。有一个$\uAutomatic值,它包含管线中的当前对象 管道是将结果从一个cmd
> Get-Something # this returns an object and display it to the output.
# Now I want to assign that object to some variable
> $anObj = ???
不完全是。有一个$\uAutomatic值,它包含管线中的当前对象 管道是将结果从一个cmdlet传递到下一个cmdlet的常用方法,cmdlet被设置为接受来自管道或管道中对象属性的参数,从而使“last result”变量的使用不相关 仍然有些情况确实需要对“管道”对象的特定引用,对于那些情况,有$自动值 下面是它的用法示例:下面是powershell的自动变量列表:
在PythScript中脚本的编程风格与Python中的编程风格不同(Python需要不同于C++的风格)
Powershell的构建是为了广泛使用管道,如果您想将管道分解为更具程序性的分步结构,则需要将结果保存在命名变量中,而不是自动变量中。不,没有这样的自动变量 你必须做到:
$output = Get-Something
$output
$anObj = $output
要获得行为还可以打印命令的结果,并使用OutVariable参数捕获输出对象,然后使用$anObj显示变量内容
Get-Something -OutVariable anObj
最后一个需要做大量工作但IMO会满足您的要求的选项是:创建一个覆盖默认值的代理(如果您没有将-*输出到其他内容,则总是在管道末尾隐式调用)
Jeffrey Snover在PowerShell的一次深度潜水(我想这是第一次)中对此做了介绍,你可以在上面找到他使用的脚本(包括上面提到的默认脚本)。您还可以从中观察以了解整个概念。使用模块PowerShellCookbook并添加一个调用以将ObjectCollector添加到启动脚本中如何使用“r”(调用历史的别名)调用最后一个命令,并将其包装在括号()中以首先执行它 是的,这将重新运行最后一个命令,但在我的使用案例中,这是迄今为止最精简的解决方案,特别是在我没有意识到首先需要最后一个命令输出的时候 它还保持对象结构的完整性
PS C:\Users\user> Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
---- -------------------- ------- ------ ---------- ---------
Ethernet Intel(R) Ethernet Connection I217-LM 3 Up XX-XX-XX-XX-XX-XX 100 Mbps
PS C:\Users\user> (r) |where {$_.LinkSpeed -eq "100 Mbps"}
Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
---- -------------------- ------- ------ ---------- ---------
Ethernet Intel(R) Ethernet Connection I217-LM 3 Up XX-XX-XX-XX-XX-XX 100 Mbps
PS C:\Users\user> (r).MacAddress
Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
XX-XX-XX-XX-XX-XX
对于我的特定用例,我正在从PowerShell运行一个批处理文件,我想实时打印该批处理文件的输出,并将输出保存到一个变量中。我可以通过管道将呼叫操作符的输出传输到
Tee对象来实现这一点:
$args = @('-r', '-a');
& "C:\myFile.bat" $args | Tee-Object -Variable output;
$output | Set-Clipboard;
第一个命令设置批处理文件的参数。第二个命令使用call操作符和my arguments运行批处理文件,并将输出传输到Tee Object
命令,该命令从call操作符实时打印输出,但也将所有信息保存到名为output的新变量中。最后一个命令只是将$output
的内容复制到剪贴板
Tee对象
还允许将输出保存到文件(Unicode编码),如果需要保存到文件和变量(除了打印到控制台),我可以在一个管道中将对Tee对象的多个调用链接在一起。有关更多信息,请参阅此链接:
如上所述,对此没有内置支持,但这里有
简单但次优的PSv3+自定义解决方案
:
注:
- 有关适当但非平凡的解决方案,请参阅
- 将此功能构建到未来的PowerShell核心版本(撰写本文时的当前版本是PowerShell[Core]7.0)中是一个很好的选择
将以下内容添加到您的
$PROFILE
文件中:
# Store previous command's output in $__
$PSDefaultParameterValues['Out-Default:OutVariable'] = '__'
如何命名变量(例如本例中的$\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
这将捕获交互式会话中变量$\uuuuuu
中最近执行的PowerShell命令[产生终端输出]的终端绑定输出,
借助PowerShell全局预设参数默认值的功能-请参阅
-OutVariable
是一个用于在变量中收集cmdlet/advanced函数的输出对象的函数,上面的定义将此参数隐式应用于所有Out Default
调用,而每当PowerShell向终端输出某些内容时,会在后台调用该参数-但是,注意下面提到的例外情况
注意事项:
- 如果需要,使用
$saved=$\uuuuuuuuuuuuuuu.Clone()
保存捕获的输出供以后使用,因为每个命令上都会重新分配$\uuuuuuuuuuuuuuuuuuu>(当然,如果您提前知道要保留命令的输出,请使用分配开始:$saved=
)
- 请注意,仅
$saved=$\uuuu
不起作用,因为这使得$saved
指向与$\uuuu
相同的[ArrayList]
实例,该实例在下一个命令中重新填充
- 在以下情况下不捕获输出:
- 外部程序的输出,例如
git
,因为按照设计,PowerShell将外部程序的输出流直接传递到终端(除非它们被重定向或捕获),因此不会调用输出默认值
。最简单的解决方法是通过管道将输出写入到(类似于*>&1
的方法无法通过PowerShell流显式路由);e、 g:
whoami.exe |写入输出#$uuuu现在已填充
- 来自co的输出
$UtilityPath = ""
(UpdateUtility.exe $ArgList 2>&1) | % {
If ($_ -Is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
}
Else {
$_
$UtilityPath = $_
}
}
$CommandOutput = ""
SomeOtherCommand | % {
$CommandOutput += "$_`r`n"
$_
}
#
# Wrapping an exiting command with a function that uses
# steppable pipelines to "remote-control" the wrapped command.
function Out-Default
{
[CmdletBinding(ConfirmImpact="Medium")]
param(
[Parameter(ValueFromPipeline=$true)]
[System.Management.Automation.PSObject] $InputObject
)
begin {
$wrappedCmdlet = $ExecutionContext.InvokeCommand.GetCmdlet(
"Out-Default")
$sb = { & $wrappedCmdlet @PSBoundParameters }
$__sp = $sb.GetSteppablePipeline()
$__sp.Begin($pscmdlet)
}
process {
$do_process = $true
if ($_ -is [System.Management.Automation.ErrorRecord]) {
if ($_.Exception -is
[System.Management.Automation.CommandNotFoundException]) {
$__command = $_.Exception.CommandName
if (test-path -path $__command -pathtype container) {
set-location $__command
$do_process = $false
}
elseif ($__command -match '^http://|\.(com|org|net|edu)$') {
if ($matches[0] -ne "http://") {$__command = "HTTP://" +
$__command }
# [diagnostics.process]::Start($__command)
start-process $__command
$do_process = $false
}
}
}
if ($do_process) {
$global:LAST = $_;
$__sp.Process($_)
}
}
end {
$__sp.End()
}
}