web-dev-qa-db-ja.com

PowerShell-「Set-StrictMode-versionlatest」を使用して変数値をテストするにはどうすればよいですか?

PowerShellスクリプトを作成し始めたところですが、変数の値のテストで問題が発生しています。ばかげた間違いを見つけるために、特に学習中は、すべての警告を有効にしてすべてを実行しようとしています。そのため、CTPV3を使用しており、「set-strictmode-versionlatest」でstrictモードをオンに設定しています。しかし、入力変数の値をチェックすることで障害にぶつかっています。これらの変数は、まだ設定されている場合とされていない場合があります。

# all FAIL if $var is undefined under "Set-StrictMode -version latest"
if ( !$var ) { $var = "new-value"; } 
if ( $var -eq $null ) { $var = "new-value"; } 

厳密モードをオフにしない限り、変数が欠落しているときに警告を発生させない値が変数にあるかどうかをテストする方法が見つかりません。そして、変数をテストするためだけに、あちこちで厳密モードのオンとオフを切り替えたくありません。どこかでオンに戻すのを忘れてしまい、ひどく散らかっているように見えます。それは正しくありえません。何が足りないのですか?

15
user62129

ここでは、存在と価値という2つのことを実際にテストしています。そして、存在テストは、厳密モード操作で警告を発生させるテストです。したがって、テストを分離します。 PowerShellは変数を(ファイルまたはレジストリプロバイダーのように)単なる別のプロバイダーと見なし、すべてのPowerShell変数はファイルルートフォルダードライブ「変数:」と呼ばれるものとして存在することを思い出してください。 、他のファイルの存在をテストするために通常使用するのと同じメカニズムを使用できることが明らかになります。したがって、「test-path」を使用します。

if (!(test-path variable:\var)) {$var = $null} # test for EXISTENCE & create
if ( !$var ) { $var = "new-value"; }           # test the VALUE

現在の厳密モードは、親スコープに影響を与えることなく、子スコープで変更できることに注意してください(スクリプトブロックなど)。したがって、周囲のプログラムの厳密さに影響を与えることなく、厳密モードの削除と変数の設定をカプセル化するスクリプトブロックを作成できます。スコープが可変であるため、少し注意が必要です。私が考えることができる2つの可能性:

#1-スクリプトブロックから値を返す

$var = & { Set-StrictMode -off; switch( $var ) { $null { "new-value" } default { $var } }}

または#2-スコープ修飾子を使用する

& { Set-StrictMode -off; if (!$var) { set-variable -scope 1 var "new-value" }}

おそらく、これらの最悪の部分は、エラーが発生しやすい$ varの繰り返し使用です(先頭の$がある場合とない場合の両方)。エラーが発生しやすいようです。したがって、代わりにサブルーチンを使用します。

function set-Variable-IfMissingOrNull ($name, $value)
{
$isMissingOrNull = !(test-path ('variable:'+$name)) -or ((get-variable $name -value) -eq $null)
if ($isMissingOrNull) { set-variable -scope 1 $name $value }
}
set-alias ?? set-Variable-IfMissingOrNull
#...
## in use, must not have a leading $ or the Shell attempts to read the possibly non-existant $var
set-VarIfMissingOrNull var "new-value"
?? varX 1

これはおそらく私がそれをスクリプト化する方法です。

EDIT:あなたの質問についてもう少し考えた後、私はあなたのコーディングスタイルにより近い、より単純な関数を思いつきました。この機能を試してください:

function test-variable
{# return $false if variable:\$name is missing or $null
param( [string]$name )
$isMissingOrNull = (!(test-path ('variable:'+$name)) -or ((get-variable -name $name -value) -eq $null))
return !$isMissingOrNull
}
set-alias ?-var test-variable
if (!(?-var var)) {$var = "default-value"}

お役に立てば幸いです。

41
rivy

まず、私はロイの答えが大好きで、完全で簡潔です。変数がすでに設定されている場合にのみ、変数を設定しようとしているように思われることをお伝えしたいと思います。これは、読み取り専用の変数または定数の仕事のようです。

変数を読み取り専用、定数にするには、次を使用します。

Set-Variable

get-help Set-Variable -fullから

-- ReadOnly: Cannot be deleted or changed without the Force parameter.
-- Constant: Cannot be deleted or changed. Constant is valid only when
creating a new variable. You cannot set the Constant option on an
existing variable.
3
EdgeVB