Как написать сценарий PowerShell, который принимает входные данные конвейера?


Я пытаюсь написать сценарий PowerShell, который может получить ввод конвейера (и, как ожидается, сделает это), но пытается что-то вроде

ForEach-Object {
   # do something
}

не работает при использовании скрипта из командной строки следующим образом:

1..20 | .test.ps1

есть ли способ?

примечание: Я знаю о функциях и фильтрах. Это не то, что я ищу.

4 73

4 ответа:

это работает, и есть наверное и другие способы сделать это:

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

17: 12: 42 PS>1..20/. \cmd-input. ps1
1
2
3
-- СНиП --
18
19
20

найдите "powershell $input variable", и вы найдете дополнительную информацию и примеры.
Пара здесь:
функции и фильтры PowerShell PowerShell Pro!
(см. раздел "Использование специальной переменной PowerShell "$input"")
"Скрипты, функции и блоки скриптов имеют доступ к переменной $input, которая предоставляет перечислитель над элементами во входящем конвейере. "
или
$input gotchas " PowerBlog Дмитрия PowerShell и за его пределами
"... в основном $input в перечислителе, который обеспечивает доступ к конвейеру, который у вас есть."

для командной строки PS, а не командная строка DOS Командный Процессор Windows.

в v2 вы также можете принять ввод конвейера (по propertyName или byValue), добавить псевдонимы параметров и т. д.:

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

вы можете написать фильтр, который является частным случаем функции, вот так:

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

или вы можете создать аналогичную функцию, например:

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

вышеизложенное работает как интерактивная функция definiton или если в скрипте можно поставить точку в вашей глобальной сессии (или в другом скрипте). Однако ваш пример показал, что вам нужен скрипт, поэтому здесь он находится в скрипте, который можно использовать напрямую (не требуется расставлять точки):

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

С PowerShell V2, это немного изменяется с помощью "расширенных функций", которые включают функции с теми же функциями привязки параметров, что и скомпилированные командлеты. Смотрите это блоге для примера различий. Также обратите внимание, что в этом случае расширенные функции не используют $_ для доступа к объекту конвейера. С помощью расширенных функций объекты конвейера привязываются к параметру так же, как и к командлету.

ниже приведены простейшие возможные примеры скриптов / функций, которые используют конвейерный ввод. Каждый из них ведет себя так же, как конвейер для командлета "echo".

Как Скрипт:

# Эхо-Труба.пс1
  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
}

функции:

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

например.

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