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 = ???
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.
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.
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.
No there is not automatic variable like that.
You have to do:
$output = Get-Something $output $anObj = $output
to get the behaviour
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>
).
$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
.
$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 $null
s leaves any previous $__
value intact.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With