How to compare, match, and append multiple values in multiple CSV files?

非 Y 不嫁゛ 提交于 2020-01-06 04:03:06

问题


I'm trying to figure out the best way to do this, and I'm not sure how to Import-Csv with 2 different files through the same pipeline and export a value found...

So lets start with CSV file 1: I only want the values for LoginNumber where Type = H and (ContractorDomain -ne $null -or ContractorDomain -ne ""). For example, this should only pull values 0031482 and 2167312 from below.

Note: I only added spaces and arrows to make it easier to read as columns here. The csv files have no spaces between the column values or arrows.

"LoginNumber","Type","ContractorDomain"
"0031482"    ,"H"   ,"P12345"  <<
"1251632"    ,"P"   ,"A52671"
"2167312"    ,"H"   ,"425126"  <<
"0598217"    ,"L"   ,""
"1405735"    ,"H"   ,""
"2058194"    ,"A"   ,"L21514"

When the value number for LoginNumber (based on conditions explained above) is found, search for it in CSV file 2. Then grab the value of AccountStatus and SamAccountName for the respective value of UserIDNumber.

"SamAccountName","UserIDNumber","AccountDescriptionDetails","AccountStatus"
"jd12395"       ,"0052142"     ,"Company CEO"              ,"Enabled"
"jwet"          ,"2167312"     ,"Software Developer"       ,"Disabled"  <<
"1b3gas5"       ,"1385293"     ,"Project Manager"          ,"Disabled"
"632g1fsa"      ,"0031482"     ,"QA Tester"                ,"Enabled"   <<
"4126hs"        ,"0000418"     ,"Program Manager"          ,"Disabled"
"axv"           ,"1840237"     ,"Accountant Administrator" ,"Disabled"

For the 3rd CSV file we have the following:

"domainName","SameAccountName","DateExpired"
"TempDomain","jwet"           ,"20151230"    <<
"PermDomain","p21942"         ,""
"PermDomain","qz231034"       ,""
"TempDomain","632g1fsa"       ,"20151231"    <<
"TempDomain","ru20da2bb22"    ,"20160425"

Next, for the 3rd file, I want to add the column to plug in the Disabled and Enabled values (or User Match Not Found value):

"domainName","SameAccountName","DateExpired","UserStatus"
"TempDomain","jwet"           ,"20151230"   ,"Disabled"               <<
"PermDomain","p21942"         ,""           ,"User Match Not Found"
"PermDomain","qz231034"       ,""           ,"User Match Not Found"
"TempDomain","632g1fsa"       ,"20151231"   ,"Enabled"                <<
"TempDomain","ru20da2bb22"    ,"20160425"   ,"User Match Not Found"

I learned how to import-csv and create new columns with something like this...

Import-Csv $file | Select-Object -Property *, @{Name="UserStatus";Expression={
  if ($true) {"fill value in here"}
}} | Export-Csv $newFile -NoType

So I'm thinking something like this. I'm just not sure how to search/find/pass multiple CSV files values through the pipeline.

Note: some of these CSV files have like 15 columns before and after the columns we are searching for. Also, some of the columns values have a comma, so I can't really rely on the -Delimiter ,. Also, some of the column values do not have " (if you were to open the CSV in txt format).


回答1:


Columns containing commas shouldn't be an issue if the values are properly quoted (i.e. if the CSV is valid). Import-Csv will correctly import a record 42,"a,b",c as three values 42, a,b and c. If your CSV isn't well-formed: fix that first.

Fetch the login IDs from the first CSV file:

$logins = Import-Csv 'C:\path\to\file1.csv' |
          Where-Object { $_.Type -eq 'H' -and $_.ContractorDomain } |
          Select-Object -Expand LoginNumber

You can simplify the ContractorDomain property check to just $_.ContractorDomain, because PowerShell interprets both an empty string and $null as a boolean value $false in that context. The same would happen for other zero or empty values (0, 0.0, empty array, etc.), but that shouldn't be an issue in your scenario.

Next create a hashtable mapping account names to their respective status. Filter the imported second CSV by the list of IDs you created before, so the hashtable contains only relevant mappings.

$accountStatus = @{}
Import-Csv 'C:\path\to\file2.csv' | Where-Object {
  $logins -contains $_.UserIDNumber
} | ForEach-Object {
  $accountStatus[$_.SamAccountName] = $_.AccountStatus
}

With that hashtable you can now add the UserStatus column to your third CSV:

(Import-Csv 'C:\path\to\file3.csv') |
  Select-Object -Property *, @{n='UserStatus';e={
    if ($accountStatus.ContainsKey($_.SameAccountName)) {
      $accountStatus[$_.SameAccountName]
    } else {
      'User Match Not Found'
    }
  }} | Export-Csv 'C:\path\to\file3.csv' -NoType

The parentheses around the Import-Csv statement ensure that the file is completely read and closed before Export-Csv starts writing to it. They're only required if you're writing the modified data back to the same file and can be omitted otherwise. The asterisk selects all imported columns, and the additional calculated property adds the new column you want to include.



来源:https://stackoverflow.com/questions/34234325/how-to-compare-match-and-append-multiple-values-in-multiple-csv-files

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