75 votes

Comment écrire un script Powershell qui accepte une entrée pipeline ?

J'essaie d'écrire un script Powershell qui peut obtenir une entrée pipeline (et est censé le faire), mais en essayant quelque chose comme

ForEach-Object {
   # do something
}

ne fonctionne pas réellement lorsque l'on utilise le script depuis la ligne de commande comme suit :

1..20 | .\test.ps1

Y a-t-il un moyen ?

Note : Je connais les fonctions et les filtres. Ce n'est pas ce que je recherche.

112voto

Shay Levy Points 41404

Dans la v2, vous pouvez également accepter des entrées pipeline (par propertyName ou byValue), ajouter des alias de paramètres, etc :

function Get-File{
    param(  
    [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)
    ]
    [Alias('FullName')]
    [String[]]$FilePath
    ) 

    process {
       foreach($path in $FilePath)
       {
           Write-Host "file path is: $path"
       }
    }
}

# test ValueFromPipelineByPropertyName 
dir | Get-File

# test ValueFromPipeline (byValue) 

"D:\scripts\s1.txt","D:\scripts\s2.txt" | Get-File

 - or -

dir *.txt | foreach {$_.fullname} | Get-File

40voto

Bratch Points 1531

Cela fonctionne et il y a probablement d'autres façons de procéder :

foreach ($i in $input) {
    $i
}

17:12:42 PS>1..20 | . \cmd -input.ps1
1
2
3
-- snip --
18
19
20

Recherchez "powershell $input variable" et vous trouverez plus d'informations et d'exemples.
Quelques-uns sont ici :
Fonctions et filtres PowerShell PowerShell Pro !
(voir la section "Utilisation de la variable spéciale PowerShell "$input"")
" Les scripts, les fonctions et les blocs script ont tous accès à la variable $input, qui fournit un énumérateur sur les éléments du pipeline entrant. "
ou
$input gotchas " Dmitry's PowerBlog PowerShell et au-delà
"... en fait, $input est un énumérateur qui donne accès au pipeline que vous avez."

Pour la ligne de commande PS, pas le Ligne de commande DOS Processeur de commandes Windows.

23voto

Keith Hill Points 566

Vous pouvez soit écrire un filtre qui est un cas spécial de fonction comme ceci :

filter SquareIt([int]$num) { $_ * $_ }

ou vous pouvez créer une fonction similaire comme suit :

function SquareIt([int]$num) {
  Begin {
    # Executes once before first item in pipeline is processed
  }

  Process {
    # Executes once for each pipeline object
    $_ * $_
  }

  End {
    # Executes once after last pipeline object is processed
  }
}

Ce qui précède fonctionne comme une définition de fonction interactive ou si dans un script peut être pointé dans votre session globale (ou un autre script). Cependant votre exemple indiquait que vous vouliez un script donc le voici dans un script qui est directement utilisable (pas de pointillé nécessaire) :

  --- Contents of test.ps1 ---
  param([int]$num)

  Begin {
    # Executes once before first item in pipeline is processed
  }

  Process {
    # Executes once for each pipeline object
    $_ * $_
  }

  End {
    # Executes once after last pipeline object is processed
  }

Avec PowerShell V2, cela change un peu avec les "fonctions avancées" qui donnent aux fonctions les mêmes caractéristiques de liaison de paramètres que les cmdlets compilés. Voir ce qui suit article de blog pour un exemple des différences. Notez également que dans ce cas de fonctions avancées, vous n'utilisez pas $_ pour accéder à l'objet pipeline. Avec les fonctions avancées, les objets pipeline sont liés à un paramètre, tout comme dans le cas d'un cmdlet.

8voto

samthebest Points 2097

Les exemples suivants sont les exemples les plus simples possibles de scripts/fonctions qui utilisent des entrées canalisées. Chacun d'entre eux se comporte de la même manière que l'utilisation de la cmdlet "echo".

En tant que scripts :

# Echo-Pipe.ps1

  Begin {
    # Executes once before first item in pipeline is processed
  }

  Process {
    # Executes once for each pipeline object
    echo $_
  }

  End {
    # Executes once after last pipeline object is processed
  }

# Echo-Pipe2.ps1

foreach ($i in $input) {
    $i
}

En tant que fonctions :

Function Echo-Pipe {
  Begin {
    # Executes once before first item in pipeline is processed
  }

  Process {
    # Executes once for each pipeline object
    echo $_
  }

  End {
    # Executes once after last pipeline object is processed
  }
}

Function Echo-Pipe2 {
    foreach ($i in $input) {
        $i
    }
}

Par exemple

PS > . theFileThatContainsTheFunctions.ps1 # This includes the functions into your session
PS > echo "hello world" | Echo-Pipe
hello world
PS > cat aFileWithThreeTestLines.txt | Echo-Pipe2
The first test line
The second test line
The third test line

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X