2015-12-21 66 views
1

我有很多重复的代码,我想清理。我知道下面的语法是不正确的,但是你能让我知道正确的方法吗?比方说,我有以下代码...如何通过函数参数传递csv列对象

Function GetColumnOneValues 
{ 
    Param ($csvFile, $ValuesWithoutNullFile) 

    Import-Csv $csvFile | Where-Object {$_.test1ColumnOne} | 
    Export-Csv $ValuesWithoutNullFile -NoTypeInformation -Force 
} 

Function GetColumnTwoValues 
{ 
    Param ($csvFile, $ValuesWithoutNullFile) 

    Import-Csv $csvFile | Where-Object {$_.test2ColumnTwo} | 
    Export-Csv $ValuesWithoutNullFile -NoTypeInformation -Force 
} 

Function GetColumnThreeValues 
{ 
    Param ($csvFile, $ValuesWithoutNullFile) 

    Import-Csv $csvFile | Where-Object {$_.test3ColumnThree} | 
    Export-Csv $ValuesWithoutNullFile -NoTypeInformation -Force 
} 

^注意重复代码

Function Main 
{ 
    $test1CsvFile = "C:\Scripts\Tests\test1.csv" 
    $test1CsvFileResults = "C:\Scripts\Tests\test1Results.csv" 
    $test2CsvFile = "C:\Scripts\Tests\test2.csv" 
    $test2CsvFileResults = "C:\Scripts\Tests\test2Results.csv" 
    $test3CsvFile = "C:\Scripts\Tests\test3.csv" 
    $test3CsvFileResults = "C:\Scripts\Tests\test3Results.csv" 

    GetColumnOneValues $test1CsvFile $test1CsvFileResults 
    GetColumnTwoValues $test2CsvFile $test2CsvFileResults 
    GetColumnThreeValues $test3CsvFile $test3CsvFileResults 
} 

Main 

相反,它应该是这样的...

Function GetColumnValues 
{ 
    Param ($csvFile, $ValuesWithoutNullFile, $ColumnName) 

    Import-Csv $csvFile | Where-Object {$ColumnName} | 
    Export-Csv $ValuesWithoutNullFile -NoTypeInformation -Force 
} 

Function Main 
{ 
    $test1CsvFile = "C:\Scripts\Tests\test1.csv" 
    $test1CsvFileResults = "C:\Scripts\Tests\test1Results.csv" 
    $test2CsvFile = "C:\Scripts\Tests\test2.csv" 
    $test2CsvFileResults = "C:\Scripts\Tests\test2Results.csv" 
    $test3CsvFile = "C:\Scripts\Tests\test3.csv" 
    $test3CsvFileResults = "C:\Scripts\Tests\test3Results.csv" 

    $column1 = $_.test1ColumnOne 
    $column2 = $_.test2ColumnTwo 
    $column3 = $_.test3ColumnThree 

    GetColumnValues $test1CsvFile $test1CsvFileResults $column1 
    GetColumnValues $test2CsvFile $test2CsvFileResults $column2 
    GetColumnValues $test3CsvFile $test3CsvFileResults $column3 
} 

Main 

然而,代替打印出非空值的函数,它会打印一个空白的csv文件。

使用这些CSV文件来测试代码...

csvFile1 ...

test1ColumnOne,test1ColumnTwo,test1ColumnThree 
qwer,, 
,qwer, 
,,qwer 

csvFile2 ...

test2ColumnOne,test2ColumnTwo,test2ColumnThree 
asdf,, 
,asdf, 
,,asdf 

csvFile3 ...

test3ColumnOne,test3ColumnTwo,test3ColumnThree 
zxcv,, 
,zxcv, 
,,zxcv 

结果应该是...

test1Results.csv ...

"test1ColumnOne","test1ColumnTwo","test1ColumnThree" 
"qwer","","" 

test2Results.csv ...

"test2ColumnOne","test2ColumnTwo","test2ColumnThree" 
"","asdf","" 

test3Results.csv ...

"test3ColumnOne","test3ColumnTwo","test3ColumnThree" 
"","","zxcv" 
+0

'(进口-CSV $文件)。 ColumnName' ....从某种意义上说是列对象。你想要名称还是位置?你只想要值或对象列? – Matt

+0

没有“列对象”。 CSV值被读入对象的属性中,其中每个对象代表CSV的一行。你的代码应该做什么?你想删除空字段的行吗?在特定列中有空字段的行?仅提取一列并删除空值? “正确的语法”取决于期望的结果。 –

+0

我更新了问题。让我知道它是否仍然没有意义。要回答你的问题,我的代码应该做什么,我有很多脚本利用这段代码用于不同的目的。但代码重复有点极端,我想知道是否有一种方法可以通过'$ _。name'作为函数的参数。 –

回答

2

如果你想从一个CSV列清空值,保留该列的非空值的列表,我会用一个泛型函数这样做:

function Remove-EmptyValues { 
    Param(
    [Parameter(
     Mandatory=$true, 
     Position=0, 
     ValueFromPipeline=$true, 
     ValueFromPipelineByPropertyName=$true 
    )] 
    [object[]]$Csv, 
    [Parameter(Mandatory=$true, Position=1)] 
    [string]$ColumnTitle 
) 

    Process { 
    $Csv | Select-Object -Expand $ColumnTitle | Where-Object { $_ } 
    } 
} 

,因此它可以像这样使用

$csv = Import-Csv 'C:\testScripts\test.csv' 
$noEmpty = Remove-EmptyValues $csv 'column A' 

或这样的:

$csv = Import-Csv 'C:\testScripts\test.csv' 
$noEmpty = $csv | Remove-EmptyValues -ColumnTitle 'column A' 

编辑:如果要删除所有行如果某一列中的值是空的,通过输入和输出文件名以及列的名称作为字符串参数:

function Remove-EmptyRecords { 
    Param(
    [Parameter(Mandatory=$true, Position=0)] 
    [string]$Source, 
    [Parameter(Mandatory=$true, Position=1)] 
    [string]$Destination, 
    [Parameter(Mandatory=$true, Position=2)] 
    [string]$ColumnTitle 
) 

    Import-Csv $Source | 
    Where-Object { $_.$ColumnTitle } | 
    Export-Csv $Destination -NoType 
} 

Remove-EmptyRecords test1.csv test1Results.csv test1ColumnOne 
Remove-EmptyRecords test2.csv test2Results.csv test2ColumnTwo 
Remove-EmptyRecords test3.csv test3Results.csv test3ColumnThree 
+0

Hi Ansgar,我只是再次更新了这个问题......所以我真的很关心获取空值,因为我在乎''传递'$ _。通过函数'Param($ _。columnName)'来创建columnName。我有搜索用户输入的字符串为每个列的函数,我有函数将列值与csv文件之间的其他列值相匹配。如果有一种方法通过函数参数传递'$ _。columnName',所有代码都可以被简化。有没有办法做到这一点? –

+0

@FiddleFreak你想要传递一列的*标题*或一列的*值*吗? –

+0

只是标题,价值将是功能的工作,找出。 –

0

不知道什么你得到在听到而你GetColumnValues因此让我们用那个目标来建立一个功能。你有一个columnName参数。还应该添加-path

Function Get-ColumnValues{ 
    Param ($Path, $ColumnName) 

    $csvData = Import-Csv $Path 
    If($ColumnName -in ($csvData | Get-Member -MemberType "NoteProperty").Name){ 
     ($csvData).$ColumnName | Where-Object{![string]::IsNullOrEmpty($_)} 
    } Else { 
     Throw "There is no column present called $ColumnName in the file $Path" 
    } 
} 

还有更多的防错,可能包含在这里,但是简单地说,这将导入CSV并返回请求的列的值,假设它的存在。

另外,如果您要导出结果,函数的名称会令人误解。你不仅得到它们,而且还设定它们。

+0

我更新了这个问题,同时注意'if($ _。test1ColumnOne){$ _。test1ColumnOne}'将返回该列中的值,只要它不为空或空字符串。 –

+0

@FiddleFreak是的。我明白代码的作用。 'IsNullOrEmpty'更易于阅读和理解。如果你坚持我会这样做,它会做同样的事情'Where-Object {$ _}' – Matt

+0

'[string] :: IsNullOrWhiteSpace'可能会更好,如果你也担心这些。我通常只是使用'Where-Object {$ _}'或类似的东西 – Matt