Pregunta ¿Cómo escribo un script de PowerShell que acepta entrada de canalización?


Intento escribir un script de PowerShell que pueda obtener entrada de canalización (y se espera que lo haga), pero intentando algo así como

ForEach-Object {
   # do something
}

en realidad no funciona cuando se usa el script desde la línea de comando de la siguiente manera:

1..20 | .\test.ps1

¿Hay alguna manera?

Nota: sé sobre funciones y filtros. Esto no es lo que estoy buscando.


73
2018-05-19 22:32


origen


Respuestas:


Esto funciona y probablemente haya otras formas de hacerlo:

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

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

Busque la variable de entrada "powershell $" y encontrará más información y ejemplos.
Una pareja está aquí:
Funciones y filtros de PowerShell PowerShell Pro!
(Consulte la sección sobre "Uso de la variable especial de PowerShell" $ input "")
"Los scripts, las funciones y los bloques de scripts tienen acceso a la variable $ input, que proporciona un enumerador sobre los elementos en la interconexión entrante".
o
$ input gotchas «Dmitry's PowerBlog PowerShell y más allá
"... básicamente, $ entrada en un enumerador que proporciona acceso a la canalización que tiene".

Para la línea de comando PS, no el Línea de comando de DOS Procesador de comandos de Windows.


38
2018-05-20 00:16



En v2 también puede aceptar la entrada de canalización (por propertyName o byValue), agregar alias de parámetro, 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

104
2018-05-20 11:34



Puede escribir un filtro que es un caso especial de una función como esta:

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

o puede crear una función similar como esta:

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
  }
}

Lo anterior funciona como una definición de función interactiva o si en una secuencia de comandos puede puntearse en su sesión global (u otra secuencia de comandos). Sin embargo, su ejemplo indicó que deseaba un script, así que aquí está en un script que se puede utilizar directamente (no se requieren puntos):

  --- 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
  }

Con PowerShell V2, esto cambia un poco con las "funciones avanzadas" que incorporan funciones con las mismas características de enlace de parámetros que poseen los cmdlets compilados. Mira esto entrada en el blog para un ejemplo de las diferencias. También tenga en cuenta que en este caso de funciones avanzadas no usa $ _ para acceder al objeto de canalización. Con funciones avanzadas, los objetos de canalización se enlazan a un parámetro como lo hacen con un cmdlet.


23
2018-05-20 00:03



Los siguientes son los ejemplos más simples posibles de scripts / funciones que usan entrada canalizada. Cada uno se comporta igual que la canalización al cmdlet "echo".

Como 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
}

Como funciones:

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
    }
}

P.ej.

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

7
2017-08-09 09:05