2016-07-25 6 views
1

Zum Beispiel Ich möchte etwas wie head, die entweder ein Array an Piped akzeptiert und dann select-object -first, oder, erhält eine Liste von Dateinamen als Parameter und gibt die ersten Zeilen von jedem. So sollte cat $filename | head arbeiten wie head $filenameWie schreibe ich eine (Unix-ähnliche) Funktion, die die Eingabe von Pipe oder Dateinamen akzeptiert?

Hier ist, was ich versucht habe, so weit:

Function head() 
{ 
    param (
     [switch] $help = $false, 
     [parameter(mandatory=$false,ValueFromPipeline=$true)] [object[]] $inputs, 
     [parameter(ValueFromRemainingArguments=$true)] [String[]] $files 
    ) 

    If($help) 
    { 
     Write-Host "usage: $($MyInvocation.MYCommand) [<file>] <numLines>" 
     return 
    } 


    $lines = 0 
    if ($files -and [int]::TryParse($files[0], [ref]$lines)) { 
     $null,$files = $files 
    } else { 
     $lines = 10 
    } 

    $input | select-object -First $lines 
    if ($files) {get-content -TotalCount $lines $files} 
} 

Aber dies bewirkt, dass die Funktion den ersten Parameter ignorieren:

C:\Users\idror.TLV-WPVAJ> head C:\temp\now.ps1 
C:\Users\idror.TLV-WPVAJ> head C:\temp\now.ps1 C:\temp\now.ps1 
Function head() 
{ 
    param (
      [switch] $help = $false, 
      [parameter(mandatory=$false,ValueFromPipeline=$true)] [object[]] $input, 
      [parameter(ValueFromRemainingArguments=$true)] [String[]] $files 
     ) 

     If($help) 
     { 
C:\Users\idror.TLV-WPVAJ> $a | head 
1 
2 
3 
C:\Users\idror.TLV-WPVAJ> $a | head 1 
head : The input object cannot be bound to any parameters for the command either because the command does not take 
pipeline input or the input and its properties do not match any of the parameters that take pipeline input. 
At line:1 char:6 
+ $a | head 1 
+  ~~~~~~ 
    + CategoryInfo   : InvalidArgument: (1:Int32) [head], ParameterBindingException 
    + FullyQualifiedErrorId : InputObjectNotBound,head 
+0

So ist die verrohrt in Array _content_ oder ein Array von Dateinamen sein würde? – briantist

+0

der Inhalt. siehe update – IttayD

+0

Sie fragen sich, wie Sie die Parametersätze schreiben können oder möchten Sie die ganze Funktion für Sie schreiben? Hast du schon mal was probiert? – briantist

Antwort

0

Sie können dies erreichen, indem Parameter Sets :

function head { 
[CmdletBinding()] 
param(
    [Parameter(
     ParameterSetName = 'Content', 
     ValueFromPipeline = $true, 
     Mandatory = $true 
    )] 
    [String[]] 
    $Content , 

    [Parameter(
     ParameterSetName = 'File', 
     ValueFromRemainingArguments = $true , 
     Mandatory = $true 
    )] 
    [String[]] 
    $Path, 

    [Parameter()] 
    [uint64] 
    $Count = 5 
) 

    Begin { 
     Write-Verbose "Parameter Set Name: $($PSCmdlet.ParameterSetName)" 
    } 

    Process { 
     Write-Verbose "Content: $Content" 
     Write-Verbose "Path: $Path" 
     Write-Verbose "Count: $Count" 
    } 
} 

Zuerst, werfen Sie einen Blick auf die Hilfe Ausgang dieses durch Get-Help head ausgeführt wird:

NAME 
    head 

SYNTAX 
    head -Content <string[]> [-Count <uint64>] [<CommonParameters>] 

    head -Path <string[]> [-Count <uint64>] [<CommonParameters>] 

Sie können sehen, dass es zwei verschiedene Sätze interpretiert, und jeder Parameter ist obligatorisch in seinen eigenen Satz.

Sie können es auch mit -Verbose nennen eine Demonstration, wie dies zu sehen arbeitet:

# Content by pipeline 
'one','two','three' | head -Verbose 

# Files as an array 
head -Verbose 'file1','file2','file3' 

# Files as remaining arguments 
head -Verbose 'file1' 'file2' 'file3' 
+0

nett. Kann ich eine Situation haben, in der ich beides haben kann? etwas wie '1,2,3 | Kopf - Zahl 3 c: \ temp \ foo 'Ausgabe' 1,2,3, eins, zwei, drei' (wo eins, zwei, drei die ersten Zeilen in foo sind)? – IttayD

+0

@IttayD möglicherweise, aber es kann ein mehrdeutiger Parametersatz sein, da Pipeline-Bindung nicht etwas ist, das die Engine verwendet, um zwischen Parametern zu unterscheiden; mit anderen Worten, wenn Sie es nicht per Pipeline aufrufen, würde es nicht wissen, ob die einzelne Zeichenkette, die Sie gesendet haben, ein Dateiname oder Inhalt war (denke ich). Du müsstest damit experimentieren. Siehe [meine Antwort hier für Tipps zur Fehlersuche bei Parametersätzen] (http://stackoverflow.com/a/37074811/3905079). – briantist

Verwandte Themen