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

我正在寻找一个类似于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值,它包含管线中的当前对象

管道是将结果从一个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()
        }
      
      }