Share via


about_ForEach

Aggiornamento: agosto 2012

Si applica a: Windows PowerShell 2.0, Windows PowerShell 3.0

ARGOMENTO

about_Foreach

DESCRIZIONE BREVE

Descrive un comando del linguaggio che è possibile usare per scorrere tutti gli elementi di una raccolta di elementi.

DESCRIZIONE LUNGA

L'istruzione Foreach (nota anche come ciclo Foreach) è un costrutto di linguaggio per seguire la sequenza (con iterazione) di una serie di valori in una raccolta di elementi.

Il tipo di raccolta più semplice e comune da scorrere è una matrice. All'interno di un ciclo Foreach in genere vengono eseguiti uno o più comandi su ogni elemento di una matrice.

Sintassi

Di seguito viene illustrata la sintassi di ForEach:

          foreach ($<item> in $<collection>){<statement list>}

Sintassi semplificata

A partire da Windows PowerShell® 3.0, la sintassi con parole chiave del linguaggio, come Where e ForEach, è stata semplificata. Gli operatori di confronto che funzionano sui membri di una raccolta vengono trattati come parametri. È possibile usare un metodo nei membri di una raccolta senza inserirlo in un blocco di script o aggiungendo la variabile automatica "$_.". Considerare i due esempi seguenti:

          dir cert:\ -Recurse | foreach GetKeyAlgorithm
          dir cert:\ -Recurse | foreach {$_.GetKeyAlgorithm()}

Anche se entrambi i comandi funzionano, il primo restituisce risultati senza usare un blocco di script o la variabile automatica $_.. Il metodo GetKeyAlgorithm viene considerato come un parametro di ForEach. Il primo comando restituisce gli stessi risultati ma senza errori, in quanto la sintassi semplificata non tenta di restituire i risultati per gli elementi per i quali l'argomento specificato non era applicabile.

In questo esempio la descrizione della proprietà Get-Process viene passata come argomento del parametro dell'istruzione ForEach. I risultati sono le descrizioni dei processi attivi.

          Get-Process | ForEach Description

Istruzione Foreach all'esterno di una pipeline di comandi

La parte dell'istruzione Foreach racchiusa tra parentesi rappresenta una variabile e una raccolta da iterare. Windows PowerShell crea la variabile ($<elemento>) automaticamente quando è in esecuzione il ciclo Foreach. Prima di ogni iterazione del ciclo, la variabile è impostata su un valore nella raccolta. Il blocco che segue un'istruzione Foreach {<elenco di istruzioni>} contiene un set di comandi da eseguire su elemento in una raccolta.

Esempi

Ad esempio, il ciclo Foreach nell'esempio seguente visualizza i valori nella matrice $letterArray.

        
          $letterArray = "a","b","c","d"
          foreach ($letter in $letterArray)
          {
              Write-Host $letter
          }

In questo esempio la matrice $letterArray viene creata e inizializzata con i valori di stringa "a", "b", "c" e "d". La prima volta che viene eseguita l'istruzione Foreach, la variabile $letter viene impostata come primo elemento in $letterArray ("a"). Viene quindi usato il cmdlet Write-Host per visualizzare la lettera a. Al ciclo successivo, la variabile $letter è impostata su "b" e così via. Dopo che il ciclo Foreach ha visualizzato la lettera d, Windows PowerShell chiude il ciclo.

L'intera istruzione Foreach deve essere visualizzata in una singola riga per essere eseguita come comando al prompt dei comandi di Windows PowerShell. Se il comando viene inserito in un file di script con estensione ps1, non è necessario che l'intera istruzione Foreach sia visualizzata in una singola riga.

Le istruzioni di Foreach possono essere usate anche con i cmdlet che restituiscono una raccolta di elementi. Nell'esempio seguente l'istruzione Foreach scorre l'elenco di elementi restituito dal cmdlet Get-ChildItem.

          foreach ($file in Get-ChildItem)
          {
              Write-Host $file
          }

È possibile perfezionare l'esempio tramite un'istruzione If per limitare i risultati restituiti. Nell'esempio seguente l'istruzione Foreach esegue la stessa operazione di ciclo dell'esempio precedente, ma aggiunge un'istruzione If per limitare i risultati ai file di dimensioni maggiori di 100 kilobyte (KB):

          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file
              }
          }

In questo esempio, il ciclo Foreach usa una proprietà della variabile $file per eseguire un'operazione di confronto ($file.length -gt 100KB). La variabile $file contiene tutte le proprietà dell'oggetto restituito dal cmdlet Get-ChildItem. Pertanto, è possibile che venga restituito più di un nome di file. Nell'esempio successivo, Windows PowerShell restituisce la lunghezza e l'ora dell'ultimo accesso all'interno dell'elenco di istruzioni:

          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file
                  Write-Host $file.length
                  Write-Host $file.lastaccesstime
              }
          }

In questo esempio, l'utente non è limitato all'esecuzione di un singolo comando in un elenco di istruzioni.

È anche possibile usare una variabile all'esterno di un ciclo Foreach e incrementare la variabile all'interno del ciclo. Nell'esempio seguente vengono contati i file di dimensioni superiori a 100 KB:

          $i = 0
          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file "file size:" ($file.length / 
          1024).ToString("F0") KB
                  $i = $i + 1
              }
          }
          if ($i -ne 0)
          {
              Write-Host
              Write-Host $i " file(s) over 100 KB in the current 
          directory."}
          else 
          {
              Write-Host "No files greater than 100 KB in the current 
          directory."
          }

Nell'esempio precedente, la variabile $i è impostata su 0 all'esterno del ciclo e viene incrementata all'interno del ciclo per ogni file maggiore di 100 KB. Quando il ciclo viene chiuso, un'istruzione If restituisce il valore di $i per visualizzare un conteggio di tutti i file che superano i 100 KB. In alternativa, viene visualizzato un messaggio che informa che non sono stati trovati file di dimensioni superiori a 100 KB.

L'esempio precedente dimostra anche come formattare i risultati della lunghezza dei file:

          ($file.length / 1024).ToString("F0")

Il valore viene diviso per 1.024 per visualizzare i risultati in kilobyte anziché in byte e il valore risultante viene formattato usando l'identificatore di formato a virgola fissa per rimuovere i valori decimali dal risultato. Il valore 0 impedisce all'identificatore di formato di mostrare cifre decimali.

L'istruzione Foreach all'interno di una pipeline dei comandi

Quando Foreach appare in una pipeline dei comandi, Windows PowerShell usa l'alias foreach, che chiama il comando ForEach-Object. Quando si usa l'alias foreach in una pipeline dei comandi, non si include la sintassi ($<elemento> in $<raccolta>) come accade con l'istruzione Foreach. Ciò avviene perché il comando precedente nella pipeline fornisce queste informazioni. Se usata in una pipeline dei comandi, la sintassi dell'alias foreach è la seguente:

          <command> | foreach {<command_block>}

Ad esempio, il ciclo Foreach nel comando seguente visualizza i processi con un working set (utilizzo della memoria) maggiore di 20 megabyte (MB).

Il comando Get-Process ottiene tutti i processi del computer. L'alias Foreach esegue i comandi nel blocco di script in ogni processo nella sequenza.

L'istruzione IF seleziona i processi con un working set (WS) di dimensioni maggiori di 20 megabyte. Il cmdlet Write-Host scrive il nome del processo seguito da un carattere di due punti (:). Divide il valore del working set, archiviato in byte, per 1 MB al fine di ottenere il valore del working set in megabyte. Converte quindi il risultato da valore doppio a stringa. Il valore viene visualizzato come numero a virgola fissa con zero decimali (F0), un separatore (" ") e quindi "MB".

          Write-Host "Processes with working sets greater than 20 MB."
          Get-Process | foreach { 
             if ($_.WS -gt 20MB)
             { Write-Host $_.name ": " ($_.WS/1MB).ToString("F0") MB -Separator ""}
          }

L'alias foreach supporta anche blocchi di comandi iniziali, centrali e finali. I blocchi di comandi iniziali e finali vengono eseguiti una volta sola, mentre quello centrale viene eseguito ogni volta il ciclo Foreach scorre una raccolta o una matrice.

Se usato in una pipeline dei comandi con un set di blocchi di comandi iniziali, centrali e finali, la sintassi dell'alias foreach è la seguente:

          <command> | foreach {<beginning command_block>}{<middle 
          command_block>}{<ending command_block>}

L'esempio seguente illustra l'utilizzo dei blocchi di comando iniziali, centrali e finali.

          Get-ChildItem | foreach {
          $fileCount = $directoryCount = 0}{
          if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{
          "$directoryCount directories and $fileCount files"}

Il blocco iniziale crea e inizializza due variabili su 0:

          {$fileCount = $directoryCount = 0}

Il blocco centrale valuta se ogni elemento restituito da Get-ChildItem è una directory o un file:

          {if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}

Se l'elemento restituito è una directory, la variabile $directoryCount viene incrementata di 1. Se l'elemento non è una directory, la variabile $fileCount viene incrementata di 1. Il blocco finale viene eseguito dopo il completamento dell'operazione di ciclo del blocco centrale e quindi restituisce i risultati dell'operazione:

          {"$directoryCount directories and $fileCount files"}

Usando la struttura dei blocchi di comandi iniziali, centrali e finali e l'operatore pipeline, è possibile riscrivere l'esempio precedente per trovare tutti i file di dimensioni maggiori di 100 KB, come indicato di seguito:

          Get-ChildItem | foreach{
              $i = 0}{
              if ($_.length -gt 100KB)
              {
                  Write-Host $_.name "file size:" ($_.length / 
          1024).ToString("F0") KB
                  $i++
              }
              }{
              if ($i -ne 0)
              {
                  Write-Host
                  Write-Host "$i file(s) over 100 KB in the current 
          directory."
              }
              else 
              {
              Write-Host "No files greater than 100 KB in the current 
          directory."}
              }

Nell'esempio seguente, in cui una funzione restituisce le funzioni usate negli script e nei moduli di script, viene illustrato come usare il metodo MoveNext (che funziona in modo analogo a "skip X" in un ciclo For) e la proprietà Current della variabile $foreach all'interno di un blocco di script foreach, anche se vi sono definizioni di funzioni con spaziatura insolita o incoerente che si estendono su più righe per dichiarare il nome della funzione. L'esempio funziona anche se sono presenti commenti nelle funzioni usate in uno script o in un modulo di script.

         function Get-FunctionPosition {
             [CmdletBinding()]
             [OutputType('FunctionPosition')]
             param(
                 [Parameter(Position=0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
                 [ValidateNotNullOrEmpty()]
                 [Alias('PSPath')]
                 [System.String[]]
                 $Path
             )
             process {
                 try {
                     $filesToProcess = if ($_ -is [System.IO.FileSystemInfo]) {
                         $_
                     } else {
                         Get-Item -Path $Path
                     }
                     foreach ($item in $filesToProcess) {
                         if ($item.PSIsContainer -or $item.Extension -notin @('.ps1','.psm1')) {
                             continue
                         }
                         $tokens = $errors = $null
                         $ast = [System.Management.Automation.Language.Parser]::ParseFile($item.FullName,([REF]$tokens),([REF]$errors))
                         if ($errors) {
                             Write-Warning "File '$($item.FullName)' has $($errors.Count) parser errors."
                         }
                         :tokenLoop foreach ($token in $tokens) {
                             if ($token.Kind -ne 'Function') {
                                 continue
                             }
                             $position = $token.Extent.StartLineNumber
                             do {
                                 if (-not $foreach.MoveNext()) {
                                     break tokenLoop
                                 }
                                 $token = $foreach.Current
                             } until ($token.Kind -in @('Generic','Identifier'))
                             $functionPosition = [pscustomobject]@{
                                       Name = $token.Text
                                 LineNumber = $position
                                       Path = $item.FullName
                             }
                             Add-Member -InputObject $functionPosition -TypeName FunctionPosition -PassThru
                         }
                     }
                 } catch {
                     throw
                 }
             }
         }

VEDERE ANCHE

about_Automatic_Variables

about_If

Foreach-Object