2012-10-24 55 views
2

在「開關」中修改正在評估的變量並使其更改匹配,有沒有辦法?在switch語句中更改評估程序

$var = "a" 
switch ($var){ 

    "a" {Write-Host "1st match for 'a'"} 
    "b" {Write-Host "1st match for 'b'"} 
    "a" {Write-Host "2nd match for 'a'"; $var = "b" ; continue} 
    "b" {Write-Host "2st match for 'b'"} 
} 

我希望能夠得到上面的匹配:

爲對 'B'

$Destination = "vmstores:\[email protected]\Training\Local-B\David" #is a param of my function, which could be a bunch of different types of object. 

$DestinationType = $Destination.GetType().Name 

    switch ($DestinationType){ 
     "String" { 
      if ((Test-Path $Destination) -eq $true){ 
       if ((Get-Item $Destination).GetType().Name -eq "DatastoreFolderImpl"){ 
        $DestinationType = "DatastoreFolderImpl" 
        if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){ 
        Write-Warning "Destination File exists..." 
        $DestinationExists = $true 
        } 
       } 
       elseif ((Get-Item $Destination).GetType().Name -eq "DatastoreFileImpl"){ 
        $DestinationType = "DatastoreFileImpl" 
        Write-Warning "Destination File exists..." 
        $DestinationExists = $true 
       } 
      } 
      ; continue 
     } 
     "DirectoryInfo" { 
      if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      ; break 
     } 
     "FileInfo" { 
      if ((Test-Path $Destination) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      ; break 
     } 
     "DatastoreFileImpl" { 
      if ((Test-Path $Destination) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      ; break 
     } 
     "DatastoreFolderImpl" { 
      if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      ; break 
     } 
     "NasDatastoreImpl" { 
      New-PSDrive -Name "DestMount" -Root \ -PSProvider VimDatastore -Datastore $Destination | Out-Null 
      if ((Test-Path ("DestMount:").insert(10,"\").Insert(11,$SourceVMXShort)) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      $Destination = ("DestMount:").insert(10,"\") 
      ; break 
     } 
     "VMFSDatastoreImpl" { 
      New-PSDrive -Name "DestMount" -Root \ -PSProvider VimDatastore -Datastore $Destination | Out-Null 
      if ((Test-Path ("DestMount:").insert(10,"\").Insert(11,$SourceVMXShort)) -eq $true){ 
       Write-Warning "Destination File exists..." 
       $DestinationExists = $true 
      } 
      $Destination = ("DestMount:").insert(10,"\") 
      ; break 
     } 

    } 
'一'
第二節比賽 'A'
第二節比賽第一個比賽

正如你所看到的,如果我可以更新$ DestinationType,那麼我可以在其他開關塊中重新使用該語句,而不是額外的「ifs」,這將更加優雅

回答

0

雖然我不認爲你可以改變switch語句變量中間檢查,你可以做嵌套switch語句。此代碼給你的要求的輸出:

$var = "a" 
switch ($var){ 
    "a" {Write-Host "1st match for 'a'"} 
    "b" {Write-Host "1st match for 'b'"} 
    "a" {Write-Host "2nd match for 'a'" 
      $var = "b" 
      switch ($var) { 
       "b" {Write-Host "2st match for 'b'"} 
      } #End sub-switch 
     } #End "A" check 
} #End Primary switch 

現在,我不知道你的總體目標是什麼,可能會有更好的方式與功能,這樣做到這一點。

編輯更新後的問題和意見:

從尋找更新的代碼,你可以拉,設置$DestinationExists = $true一個if語句。您可能可以重新組織您的if報表,以便它們只顯示一次。不幸的是,沒有辦法讓開關語句改變變量中間開關。從你的評論,也許你可以添加一個額外的參數,將決定類型,所以你可以爲我們一個基於類型的大型開關語句。這樣的事情:

switch ($DataType) { 
    "String" {<#Things to do if string#>} 
    "OtherTypes" {<#Continue like this#>} 
}#End Switch ($DataType) 

我認爲在那一點,雖然,我會開始使用參數集。這是一個博客描述約Parameter Sets

+0

我正在寫一個函數,其中一個參數可能是一些類型的對象,其中一個字符串是一個。如果它匹配'字符串',那麼我想改變我打開的變量的值,所以我不必在我的語句塊中編寫額外的'ifs'。 – wint3r

0

這是一個有點令人費解的方式來做到這一點。請注意,示例代碼與OP中的代碼相似但不相同。

add-type @" 

using System; 
using System.Collections; 
using System.Collections.ObjectModel; 
using System.Management.Automation; 

public class PSVarEnumeration : IEnumerable 
{ 
    private ScriptBlock _getterScript; 

    public PSVarEnumeration(ScriptBlock getterScript) 
    { 
     _getterScript = getterScript; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return (IEnumerator) GetEnumerator(); 
    } 

    public PSVarEnumerator GetEnumerator() 
    { 
     return new PSVarEnumerator(_getterScript); 
    } 
} 

public class PSVarEnumerator : IEnumerator 
{ 
    private ScriptBlock _getterScript; 
    bool areDone = false; 

    // position isn't used for anything 
    int position = -1; 

    public PSVarEnumerator(ScriptBlock getterScript) 
    { 
     _getterScript = getterScript; 
    } 

    public bool MoveNext() 
    { 
     if (!areDone) { 
      if (Current != null) { 
      position++; 
      return true; 
      } else { 
      areDone = true; 
      return false; 
      } 
     } else { 
      return false; 
     } 
    } 

    public void Reset() 
    { 
     position = -1; 
     areDone = false; 
    } 

    object IEnumerator.Current 
    { 
     get 
     { 
      return Current; 
     } 
    } 

    public Object Current 
    { 
     get 
     { 
      Collection<PSObject> results = _getterScript.Invoke(); 
      return results[0]; 
     } 
    } 
} 

"@ 

$mySwitcher ="a" 
$mySwitcherScript = {$mySwitcher} 
$var = new PSVarEnumeration ($mySwitcherScript) 

switch ($var){ 

    "a" {Write-Host "1st match for 'a'"} 
    "b" {Write-Host "1st match for 'b'"} 
    "a" {Write-Host "2nd match for 'a'"; $mySwitcher = "b" ; continue} 
    "b" {Write-Host "2nd match for 'b'"; $mySwitcher = $null} 
} 

<# 
Output I get is: 

1st match for 'a' 
2nd match for 'a' 
1st match for 'b' 
2nd match for 'b' 

#>