Pythonインタラクティブシェルの「_」変数に匹敵する機能を探しています。PowerShellでは、次のようなものが必要です。
> Get-Something # this returns an object and display it to the output.
# Now I want to assign that object to some variable
> $anObj = ???
Pythonインタラクティブシェルの「_」変数に匹敵する機能を探しています。PowerShellでは、次のようなものが必要です。
> Get-Something # this returns an object and display it to the output.
# Now I want to assign that object to some variable
> $anObj = ???
いいえ、そのような自動変数はありません。
あなたはしなければならない:
$output = Get-Something
$output
$anObj = $output
動作を取得するには
前述のように、これに対する組み込みのサポートはありませんが、これは単純ですが、最適ではないPSv3+カスタムソリューションです。
ノート:
適切であるが重要な解決策については、BartekBの役立つ回答を参照してください。
GitHub機能リクエスト#7853は、この機能を将来のPowerShell Coreバージョンに組み込むことを要求しています(この記事の執筆時点での現在のバージョンはPowerShell(Core)7.2です)。
$PROFILE
ファイルに以下を追加します。
# Store previous command's output in $__
$PSDefaultParameterValues['Out-Default:OutVariable'] = '__'
変数に名前を付ける方法$__
(この例では(2アンダースコア)など)はユーザー次第ですが、名前の衝突に注意してください。特に$_
、多くのコンテキストで手元の入力オブジェクトを表す自動変数との衝突に注意してください。
$__
これにより、パラメーターのデフォルトをグローバルに事前設定するPowerShellの機能により、対話型セッションで変数に最後に実行されたPowerShellコマンドの端末バインド出力がキャプチャGet-Help about_Parameters_Default_Values
されます。を参照してください。
-OutVariable
は、コマンドレット/高度な関数の出力オブジェクトを変数に収集するように設計された一般的なパラメーターです。上記の定義は、このパラメーターをすべての呼び出しに暗黙的Out-Default
に適用します。このパラメーターは、PowerShellが端末に何かを出力するたびに、バックグラウンドで呼び出されます。ただし、下記の例外。
警告:
必要に応じ$saved = $__.Clone()
て、キャプチャした出力を後で使用するために保存するために使用します。これは、$__
すべてのコマンドで再割り当てされます(もちろん、コマンドの出力を保持することが事前にわかっている場合は、次で始まる割り当てを使用します$saved = <command>
)。
$saved = $__
機能しないことに注意してください。$saved
[ArrayList]
$__
次の場合、出力はキャプチャされません。
のような外部プログラムからの出力git
。これは、PowerShellが設計上、外部プログラムからの出力ストリームを直接端末に渡すため(リダイレクトまたはキャプチャされない限り)、を呼び出さないためですOut-Default
。最も簡単な回避策は、パイプを使用することWrite-Output
です(*>&1
PowerShellストリームを明示的にルーティングするようなものは機能しません)。例えば:
whoami.exe | Write-Output # $__ is now populated
Format-Custom
フォーマットコマンドレットを明示Format-Hex
的Format-List
に呼び出すコマンドからの出力- 、、、、、、Format-Table
またはFormat-Wide
。
$PSDefaultParameterValues['Format-*:OutVariable'] = '__'
が、残念ながら、これにより、の元のデータではなく、書式設定オブジェクト(命令)が収集されます。これは望ましくありません。不十分な回避策は、出力を別の変数にキャプチャすることです。これにより、ターゲットにする必要のある変数を検討する必要があるだけでなく、データではなくフォーマットオブジェクトのみが表示されます。また、コマンドレットはバックグラウンドで関与しているため、それらを明示的に使用しない場合、呼び出しなしのコマンドの出力は2回キャプチャされます。1回はデータとして、もう1回はフォーマットオブジェクトとして、もう1つの変数にキャプチャされます。$__
Format-*
Format-*
Format-*
$__
設計上の癖により、前のコマンドが単一のオブジェクトのみを出力した場合でも、$__
常に(タイプの)配列リストが含まれます。疑わしい場合は、(または)を使用して単一の出力オブジェクトを取得します。[System.Collections.ArrayList]
$($__)
$__[0]
非常に大きな出力セットを生成するコマンドに注意してください。これらはメモリ$__
に収集されます。
$__
Pythonの場合と同様に、ターミナルに出力されたオブジェクトのみをキャプチャします。_
出力を生成しないコマンドまたは$null
/の配列は$null
、以前の$__
値をそのまま残します。
コマンドの結果を出力し、OutVariableパラメーターを使用して出力オブジェクトをキャプチャし、後で$anObjを使用して変数の内容を表示することもできます。
Get-Something -OutVariable anObj
ほとんどの作業を必要とする最後のオプションですが、IMOはあなたが求めるものを提供します:Out-Defaultを上書きするプロキシを作成します(他の何かにout- *しない場合は、パイプラインの最後で常に暗黙的に呼び出されます)。
ジェフリー・スノーバーは、PowerShell Deep Divesの1つでプレゼンテーションを行いました(これが最初のものだったと思います)。彼が使用したスクリプト(上記のデフォルトを含む)は、DmitrySotnikovブログで見つけることができます。そこからビデオを見て、全体の概念を理解することもできます。
ではない正確に。パイプラインに現在のオブジェクトを含む$_自動値があります。
パイプラインは、あるコマンドレットから次のコマンドレットに結果を渡す通常の方法であり、コマンドレットは、パイプラインまたはパイプライン内のオブジェクトのプロパティからパラメーターを受け入れるように設定され、「最後の結果」変数は関係ありません。
それでも、「パイプ」オブジェクトへの特定の参照が必要な状況もあり、その場合は$_自動値があります。
使用例は次のとおりです。Where -Objectコマンドレットの使用とPowerShellの自動変数のリストは次のとおりです。第4章PowerShell自動変数
PowerShellでのスクリプトには、Pythonでのプログラミングとは異なるスタイルが必要です(PythonがC ++とは異なるスタイルを必要とするのと同じです)。
Powershellは、パイプが広く使用されるように構築されています。パイプラインをより手続き型の段階的な構造に分割する場合は、結果を自動変数ではなく名前付き変数に保存する必要があります。
最後のコマンドを「r」(Invoke-Historyの別名)で呼び出し、括弧()で囲んで最初に実行するのはどうですか?
はい、これは最後のコマンドを再実行しますが、私のユースケースでは、特に最初に最後のコマンドを出力する必要があることに気付いていない場合は、これがはるかに合理化されたソリューションです。
また、オブジェクトの構造をそのまま維持します。
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-Object
。
$args = @('-r', '-a');
& "C:\myFile.bat" $args | Tee-Object -Variable output;
$output | Set-Clipboard;
最初のコマンドは、バッチファイルの引数を設定します。2番目のコマンドは、引数を指定して呼び出し演算子を使用してバッチファイルを実行し、出力をTee-Object
コマンドにパイプします。コマンドは、呼び出し演算子からの出力をリアルタイムで出力しますが、すべての情報をoutputという新しい変数に保存します。最後のコマンドは、内容を$output
クリップボードにコピーするだけです。
Tee-Object
また、出力をファイルに保存することもできます(Unicodeエンコーディング)。 (コンソールへの印刷に加えて)ファイルとTee-Object
変数に保存する必要がある場合は、1つのパイプラインで複数の呼び出しをチェーンできます。詳細については、次のリンクを参照してください。
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/tee-object
これは、Windows PowershellinActionからのものです。これを$profileで取得すると、$lastに最後のコマンドの出力が含まれるようになります。また、ディレクトリの名前をa la zshと入力してディレクトリを変更するか、WebサイトのURLを入力してブラウザでWebサイトに移動します。Out-Defaultコマンドレットをオーバーライドして呼び出すOut-Default関数を作成します。「start-process$__ command」行を追加したので、ウェブサイトにアクセスするとosxで機能します。
これはかなり侵襲的です。後で何らかの理由で$profileで無効にしました。
#
# 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()
}
}
私にとってうまくいったアプローチは、コマンドの出力をSelect-Object
パススルーとして処理することです。たとえば、詳細な出力をに出力しstderr
、意味stdout
のある出力をに出力するコンソールEXEがありましたが、最後の行だけをキャプチャしたいと思いました。
$UtilityPath = ""
(UpdateUtility.exe $ArgList 2>&1) | % {
If ($_ -Is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
}
Else {
$_
$UtilityPath = $_
}
}
このスクリプトが呼び出され、PowerShellの出力ストリームに出力がある場合は、ハードエラーと見なされました。これは、PowerShellが外部アプリの出力を取得して出力に変換Error
する方法とうまく一致しませんでした。出力をラップするこのアプローチにより、出力の通過方法を制御したり、必要な行をキャプチャしたりすることができました。これはかなり柔軟なアプローチであり、出力をインターセプトして、出力が通過するときに必要なことをすべて実行できるように思われます。例えば:stderr
Error
stdout
$CommandOutput = ""
SomeOtherCommand | % {
$CommandOutput += "$_`r`n"
$_
}
モジュールPowerShellCookbookを使用して、スタートアップスクリプトにAdd-ObjectCollectorの呼び出しを追加します
「 (Get-History)[-1].CommandLine 」を試すことができます。