如何在Powershell cmdlet中将CSV文件的内容作为管道输入处理 [英] How can I process the content of a CSV file as Pipeline input in Powershell cmdlet
问题描述
我想使用CSV文件来提供powershell cmdlet的参数
I want to use a CSV file to feed the parameters of powershell cmdlet
Role, email, fname, lname
Admin, a@b.com, John, Smith
我要按如下方式处理cmdlet:
I want to process a cmdlet as follows:
import-csv myFile| mycmdlet | export-csv myresults
我也希望能够像这样调用cmdlet
I also want to be able to call the cmdlet like this
mycmdlet -role x -email j@b.com -fname John -lname Smith
并以类似以下对象的形式查看结果:
and see a result as an object like:
lname: "Smith"
fname: "John"
email: "j@b.com"
role: "X"
ResultData: "something else"
我不想这样做:
import-csv X.txt | foreach-object { mycmdlet -email $_.email }
在Powershell中,我想这样做:
In the powershell I wanted to do something line this:
function global:test-Pipeline{
param(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][String[]]$role,
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][String[]]$email,
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][String[]]$fname,
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][String[]]$lname )
$result = new-object psobject
process {
foreach($address in $email)
{
Do something with each role, email, fname lname
Add output to $result
}
}
End {
return $result
}
}
我敢肯定这是有可能的,我该怎么做?无需在cmdlet中处理CSV就能做到吗?
I'm sure this must be possible, how do i do it? Can it be done without having to process the CSV in the cmdlet?
推荐答案
是的,您几乎完全正确.您的参数不应使用ValueFromPipeline
,而应使用ValueFromPipelineByPropertyName
.它们应该是[String]
,而不是[String[]]
.原因是您将在每个传递"中获得与单个输入对象相对应的一组参数.
Yes, you almost have it right. Your parameters should not use ValueFromPipeline
but should use ValueFromPipelineByPropertyName
. They should be [String]
but not [String[]]
. The reason is that you are going to get a single set of parameters, corresponding to a single input object, in each "pass".
您也不需要End{}
块,应该全部在Process{}
中完成.
You also don't need the End{}
block here it should all be done in Process{}
.
function Test-Pipeline{
param(
[Parameter(ValueFromPipelineByPropertyName=$true)][String]$role,
[Parameter(ValueFromPipelineByPropertyName=$true)][String]$email,
[Parameter(ValueFromPipelineByPropertyName=$true)][String]$fname,
[Parameter(ValueFromPipelineByPropertyName=$true)][String]$lname
)
Process {
New-Object PSObject -Property @{
role = "~$role~"
email = "mailto:$email"
fname = [cultureinfo]::CurrentCulture.TextInfo.ToTitleCase($fname)
lname = [cultureinfo]::CurrentCulture.TextInfo.ToTitleCase($lname)
}
}
}
用法:
Import-Csv myData.csv | Test-Pipeline | Export-Csv tranformedData.csv -NoTypeInformation
Import-Csv myData.csv | Test-Pipeline -role "Override Role" | ConvertTo-Json
这是怎么回事?
Import-Csv
为CSV中的每一行提供一个对象,并且每个对象为CSV中的每一列都有一个属性.
What's going on?
Import-Csv
gives you one object for every row in the CSV, and each object has a property for each column in the CSV.
将其通过管道传递到另一个命令(包括函数)时,每个单独的对象一次发送一次.
When you pipe that into another command, including your function each individual object gets sent through one at a time.
您可以接受一个对象,并在命令中处理其属性.
You could accept the one object, and process its properties in the command.
这里使用ValueFromPipelineByPropertyName
所显示的内容将查看输入对象,如果存在,并且包含的属性与参数的名称(或其任何别名)匹配,则该对象的值属性将绑定到参数(除非您在调用时指定;否则它将覆盖输入值).
What you have here, using ValueFromPipelineByPropertyName
, looks at the input object, if there is one, and if it contains a property that matches the name of the parameter (or any of its aliases), then the value of that property will be bound to the parameter (unless you specified on calling; that would override the input value).
由于再次需要对象,因此在Process
块中创建了一个新对象,该对象将通过管道传递到下一个命令.
Since you want objects again as a result, you create a new object in the Process
block, which will be passed out through the pipeline to the next command.
这篇关于如何在Powershell cmdlet中将CSV文件的内容作为管道输入处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!