2015-12-16 19 views
0

我試圖通過查看CSV文件1中是否包含CSV文件2列的值來附加列。匹配哈希表中的值,同時忽略兩個CSV文件之間的大小寫敏感

我有一個CSV文件1(test1.csv):

csv1ColumnOne,csv1ColumnTwo 
1,dF3aWv 
2, 
3,ka21p 
4,NAE31 
5,dsafl 
6,nv02k 
7,qng02 
8,xcw3r 
9,dF3aW 

我有一個CSV文件2(test2.csv):

csv2ColumnOne,csv2ColumnTwo 
bbetfe,DF3AW 
asdf,dsafl 
qwer, 
zxcv,NAE31 
poiu,nbrwp1 

考慮下面的代碼...

$hashTable = @() 
Import-Csv C:\path\test1.csv | ForEach-Object { 
    $hashTable[$_.csv1ColumnOne] = $_.csv1ColumnTwo 
} 

(Import-Csv C:\path\test2.csv) | 
    Select-Object -Property *, @{n='csv1ColumnThree';e={ 
    if ($hashTable.ContainsKey($_.csv2ColumnTwo)) { 
     $_.csv2ColumnTwo 
    } elseif (-not ($_.csv2ColumnTwo)) { 
     'No value found from csv file2' 
    } else { 
     'No value found from csv file1' 
    } 
    }} | Export-Csv "C:\path\testresults.csv" -NoType 

結果如下所示:

csv2ColumnOne,csv2ColumnTwo,csv1ColumnThree 
bbetfe,DF3AW,"No value found from csv file1" 
asdf,dsafl,dsafl 
qwer,,No value found from csv file2 
zxcv,NAE31,NAE31 
poiu,nbrwp1,"No value found from csv file1" 

當相反,它應該是這樣的:

csv2ColumnOne,csv2ColumnTwo,csv1ColumnThree 
bbetfe,DF3AW,dF3aW 
asdf,dsafl,dsafl 
qwer,,"No value found from csv file2" 
zxcv,NAE31,NAE31 
poiu,nbrwp1,"No value found from csv file1" 

我之所以看到bbetfe,DF3AW,"No value found from csv file1" ins't bbetfe,DF3AW,dF3aW是因爲價值的區分大小寫的。無論如何忽略字母數字值的大小寫敏感?

+0

請注意,我不能使用'-like',因爲它會爲列'csv1ColumnThree'填充值'dF3aWv'而不是'dF3aW' ... Python有if(string.upper())之類的東西。如果PowerShell有這樣的事情會很好... –

回答

1

你可以讓它們全部小寫嗎?

$a = ipcsv 'C:\path\test1.csv' 
$a | % {$_.csv1columntwo = $_.csv1columntwo.tolower()} 
$a 

$b = ipcsv 'C:\path\test2.csv' 
$b | % {$_.csv2ColumnOne = $_.csv2ColumnOne.tolower(); $_.csv2ColumnTwo = $_.csv2ColumnTwo.tolower()} 
$b 
+0

讓我給這個鏡頭。其實我不能把它們寫成更低的,它們必須沒有被篡改,但是如果我可以將它們讀取得更低,那將起作用... –

+0

由於某種原因,這對我沒有用,我要去給一個鏡頭上面的答案,這似乎更容易,更少更改......謝謝。 –

2

爲了避免字符串爲小寫轉換,只需使用-icontains比較運營商(以下簡稱「我」的意思的情況下insenstive比較):

所以不是

If ($hashTable.ContainsKey($_.csv2ColumnTwo)){ 

試這個:

If ($hashTable.keys -icontains $_.csv2ColumnTwo){ 
+0

謝謝,現在試試這個... –

+0

由於某種原因,它仍然在打印else語句:( –

3

ContainsKey()查找已經是case-insensi略去。你只是使用了錯誤的數據結構,並以錯誤的方式使用它。

如果你想查找一個關鍵在您需要實際使用的數據,你要查找的哈希表的關鍵一個哈希表:

$hashTable[$_.csv1ColumnTwo] = $_.csv1ColumnOne 

對於仰視的東西值爲的值爲的散列表使用ContainsValue()

但是,由於您只是想檢查第一個CSV的第二列是否包含第二個CSV第二列的值,因此您並不需要散列表。一個簡單的數組就足夠了。

$list = Import-Csv 'C:\path\test1.csv' | Select-Object -Expand csv1ColumnTwo 

Import-Csv 'C:\path\test2.csv' | 
    Select-Object -Property *, @{n='csv1ColumnThree';e={ 
    if ($list -contains $_.csv2ColumnTwo) { 
     $_.csv2ColumnTwo 
    } elseif (-not ($_.csv2ColumnTwo)) { 
     'No value found from csv file2' 
    } else { 
     'No value found from csv file1' 
    } 
    }} | Export-Csv 'C:\path\testresults.csv' -NoType 

如果你不想在第二CSV「發現」空字符串簡單地排除$list元素:

$list = Import-Csv 'C:\path\test1.csv' | 
     Select-Object -Expand csv1ColumnTwo | 
     Where-Object { $_ } # allow only non-empty values 

並不是每一個問題都是釘子,所以不要嘗試修復一切都用錘子。

+0

我看到了,謝謝你對我的修正。我同意錘子理論,但是當你沒有領導開發或敏捷環境,經理希望你做出改變,並在10分鐘內將事情推出去,我幾乎沒有時間重新考慮/重新設計:( –

+0

似乎工作,如果我想使用第一個文件的值而不是將值從第二個值複製到列'csv1ColumnThree'? –

+0

您可以使用哈希表映射第一個CSV到自身的值('$ hashTable [$ _。csv1ColumnTwo] = $ _。csv1ColumnTwo'),因此您可以使用查找'$ hashTable [$ _。csv2ColumnTwo]',或者你可以像這樣從數組中獲得它:'$ v = $ _。csv2ColumnTwo; $ list |?{$ _ -eq $ v}'。 –

1

Ansgar基本上有正確的答案,但有一個錯誤。它將第二個文件中的行打印爲qwer,,,而應該打印qwer,,No value found from csv file2。如下所示,還需要在第一個if語句中添加另一個條件。

$list = Import-Csv 'C:\path\test1.csv' | Select-Object -Expand csv1ColumnTwo 

Import-Csv 'C:\path\test2.csv' | 
    Select-Object -Property *, @{n='csv1ColumnThree';e={ 
    if (($list -contains $_.csv2ColumnTwo) -and ($_.csv2ColumnTwo)) { 
     $_.csv2ColumnTwo 
    } elseif (-not ($_.csv2ColumnTwo)) { 
     'No value found from csv file2' 
    } else { 
     'No value found from csv file1' 
    } 
}} | Export-Csv 'C:\path\testresults.csv' -NoType 

第2個文件中的空值被檢查爲true,所以elseif從未被達到。

+0

感謝您發佈答案 –

相關問題