Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell: Is there an automatic variable for the last execution result?

Tags:

powershell

I'm looking for a feature comparable to Python interactive shell's "_" variable. In PowerShell I want something like this:

> Get-Something # this returns an object and display it to the output. # Now I want to assign that object to some variable > $anObj = ??? 
like image 441
KFL Avatar asked Jan 16 '13 03:01

KFL


People also ask

What does $_ do in PowerShell?

The $_ is a variable or also referred to as an operator in PowerShell that is used to retrieve only specific values from the field. It is piped with various cmdlets and used in the “Where” , “Where-Object“, and “ForEach-Object” clauses of the PowerShell.

What is the function of $input variable in PowerShell?

In the Process block of a function, the $input variable enumerates the object that is currently in the pipeline. When the Process block completes, there are no objects left in the pipeline, so the $input variable enumerates an empty collection.

What does += in PowerShell mean?

Windows PowerShell. When the value of the variable is an array, the += operator appends the values on the right side of the operator to the array. Unless the array is explicitly typed by casting, you can append any type of value to the array, as follows: PowerShell Copy.


2 Answers

No there is not automatic variable like that.

You have to do:

$output = Get-Something $output $anObj = $output 

to get the behaviour

like image 110
manojlds Avatar answered Oct 14 '22 22:10

manojlds


As stated, there's no built-in support for this, but here's a simple, but suboptimal PSv3+ custom solution:

Note:

  • For a proper, but nontrivial solution, see BartekB's helpful answer.

  • GitHub feature request #7853 asks for building this functionality into a future PowerShell Core version (the current version as of this writing is PowerShell (Core) 7.2).


Add the following to your $PROFILE file:

# Store previous command's output in $__ $PSDefaultParameterValues['Out-Default:OutVariable'] = '__' 

What to name the variable - such as $__ (2 underscores) in this example - is up to you, but beware of name collisions, notably with $_, the automatic variable that represents the input object at hand in a number of contexts.

This will capture the terminal-bound output of the most recently executed PowerShell command [that produced terminal output] in variable $__ in your interactive sessions, by way of PowerShell's ability to globally preset parameter defaults - see Get-Help about_Parameters_Default_Values.

-OutVariable is a common parameter designed to collect a cmdlet's / advanced function's output objects in a variable, and the above definition applies this parameter implicitly to all Out-Default calls, which in turn is called behind the scenes whenever PowerShell outputs something to the terminal - however, note the exceptions mentioned below.

Caveats:

  • If needed, use $saved = $__.Clone() to save the captured output for later use, given that $__ is reassigned to on every command (of course, if you know ahead of time that you want to keep a command's output, use an assignment to begin with: $saved = <command>).

    • Note that just $saved = $__ does not work, because that makes $saved point to the same [ArrayList] instance as $__, which gets repopulated on the next command.
  • Output is not captured in the following cases:

    • Output from external programs, such as git, because by design PowerShell passes the output streams from external programs directly to the terminal (unless they're redirected or captured), and therefore doesn't call Out-Default. The simplest workaround is to pipe to Write-Output (something like *>&1 to explicitly route through PowerShell streams doesn't work); e.g.:

      • whoami.exe | Write-Output # $__ is now populated
    • Output from commands that explicitly call a formatting cmdlet - Format-Custom, Format-Hex, Format-List, Format-Table, or Format-Wide.

      • It's tempting to attempt to fix that with $PSDefaultParameterValues['Format-*:OutVariable'] = '__', but, unfortunately, this would collect formatting objects (instructions) rather than the original data in $__, which is undesired. An unsatisfying workaround is to capture Format-* output in a different variable, which not only requires you to think about which variable you need to target, but you'll still only see formatting objects rather than data, and, since Format-* cmdlets are involved behind the scenes even if you don't use them explicitly, the output of commands without Format-* calls is then captured twice - once as data, in $__, and again as formatting objects, in the other variable.
  • Due to a design quirk, $__ always contains an array list (of type [System.Collections.ArrayList]), even if the previous command output only a single object. When in doubt, use $($__) (or $__[0]) to get a single output object as such.

  • Beware of commands producing very large output sets, because $__ will collect them in memory.

  • $__ will only capture objects output to the terminal - just like _ does in Python; a command that produces no output or $null / an array of $nulls leaves any previous $__ value intact.

like image 45
mklement0 Avatar answered Oct 14 '22 21:10

mklement0