How can I process the content of a CSV file as Pipeline input in Powershell cmdlet

浪尽此生 提交于 2019-12-11 03:43:11

问题


I want to use a CSV file to feed the parameters of powershell cmdlet

Role, email, fname, lname
Admin, a@b.com, John, Smith

I want to process a cmdlet as follows:

import-csv myFile| mycmdlet | export-csv myresults

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"

I didn't want to have to do this:

import-csv X.txt | foreach-object { mycmdlet -email $_.email } 

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
}

}

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?


回答1:


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".

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

Usage:

Import-Csv myData.csv | Test-Pipeline | Export-Csv tranformedData.csv -NoTypeInformation

Import-Csv myData.csv | Test-Pipeline -role "Override Role" | ConvertTo-Json

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.

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).

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.



来源:https://stackoverflow.com/questions/53291756/how-can-i-process-the-content-of-a-csv-file-as-pipeline-input-in-powershell-cmdl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!