Як написати сценарій PowerShell, який приймає введення конвеєра?


75

Я намагаюся написати сценарій PowerShell, який може отримати вхідний конвеєр (і, як очікується, це зробить), але намагаюся щось на зразок

ForEach-Object {
   # do something
}

насправді не працює при використанні сценарію з командного рядка наступним чином:

1..20 | .\test.ps1

Чи є спосіб?

Примітка: Я знаю про функції та фільтри. Це не те, що я шукаю.

Відповіді:


42

Це працює, і є, мабуть, інші способи зробити це:

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

17:12:42 PS> 1..20 | . \ cmd-input.ps1
1
2
3
- фрагмент -
18
19
20

Шукайте "вхідна змінна Powerhell $", і ви знайдете більше інформації та прикладів.
Тут є пара:
Функції та фільтри PowerShell PowerShell Pro!
(див. розділ "Використання спеціальної змінної PowerShell" $ input "")
"Сценарії, функції та блоки сценаріїв мають доступ до змінної $ input, яка забезпечує перерахування елементів у вхідному конвеєрі."
або
$ input gotchas «Дмитрій PowerBlog PowerShell і далі
" ... в основному $ введення в перечислювач, який забезпечує доступ до конвеєру, який у вас є. "

Для командного рядка PS, а не для командного рядка DOS командного процесора Windows.


Час трохи розім'яти ... просто на користь тих, хто блукає і читає це, DOS все ще доступний у всіх версіях Windows. 64 біт або 32 біт.
EBGreen

13
EBGreen, ntvdmякий є DOS VM Windows NT, більше не існує в 64-розрядних системах. неcmd.exe є DOS; це командний процесор Windows і, крім сірого тексту на чорному, взагалі нічого спільного з DOS не має.
Джої

117

У v2 ви також можете прийняти введення конвеєра (за властивістюName або 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

Все-таки функція, а не сценарій. Див. Коментар на stackoverflow.com/questions/885349/… .
Джої

6
немає biggie, збережіть тіло функції у файлі сценарію та перекладіть до сценарію: dir | . \ Get-File.ps1
Шей Леві

7
Насправді ви можете розмістити блок param () у верхній частині сценарію, не оголошуючи функцію локальною для сценарію.
Thomas S. Trias,

24

Ви можете написати фільтр, який є особливим випадком функції:

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

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

  --- 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 це трохи змінюється завдяки "розширеним функціям", які надають функції з тими ж функціями прив'язки параметрів, що й у компільованих командлетах. Див. Цю публікацію в блозі для прикладу відмінностей. Також зверніть увагу, що в цьому випадку розширених функцій ви не використовуєте $ _ для доступу до об'єкта конвеєра. За допомогою розширених функцій об'єкти конвеєра прив'язуються до параметрів так само, як це робиться з командлетом.


Я знаю про фільтри, але я хотів використовувати сценарій як елемент конвеєра, а не як функцію, визначену в сценарії. Хоча дякую.
Джої,

4
Блок процесу - це те, що ви хочете. Вона має ту перевагу, що не затримує трубопровід.
JasonMArcher

Якщо ви вказали параметр, вам слід скористатися ним. Я думав, що це частина якогось прототипу параметрів, і цікавився, чому його не використовують, чи можна використовувати замість ЦЬОГО. Витрачені цикли. Хоча відповідь все ще подобається;)
Gerard ONeill

8

Далі наведено найпростіші можливі приклади сценаріїв / функцій, які використовують конвеєрне введення. Кожен поводиться так само, як підведення до командлета "echo".

Як сценарії:

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

Як функції:

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

Навіщо повторювати відповідь, яку Кіт дав уже два роки тому?
Джої

Його відповідь містить такі проблеми: Він не містить точно того, що потрібно для відповіді на питання - квадратура тупа. Параметри функції не потрібні, ми можемо просто використовувати $ _. "Ви можете написати фільтр, який є особливим випадком такої функції" - не має граматичного сенсу, і використання фільтрів не є необхідним.
самий найкращий

Це працювало для мене на ubuntu. Відповіді вище не дали.
n.podbielski
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.