Проверьте значения файла CSV для каждой строки в другом файле CSV - PullRequest
1 голос
/ 23 апреля 2020

У меня есть два CSV-файла, где я храню данные, мне нужно проверить, существует ли значение из CSV 1 в CSV 2, и если да, то заменить это значение в file2 данными из file1, если нет, просто перейти к другой строке,

File1.csv

NO;Description
L001;DREAM
L002;CAR
L003;PHONE
L004;HOUSE
L005;PLANE

File2.csv

ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;DREAM;Scheduled;1524031200;;;1524033000;
149137;CAR;Implementation In Progress;1528588800;;;1548968400;
150564;PHONE;Scheduled;1569456000;;;1569542400;
150564;HOUSE;Scheduled;1569456000;;;1569542400;
150564;PLANE;;;;;;

Я пробовал что-то подобное, но у меня это не работает:

    $file1 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty Description
$file2 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty NO
        Import-Csv "C:\Users\file3.csv" |Where-Object {$file1 -like $_.Name} |ForEach-Object {
          $_.Name = $file2($_.NO)
    } |Out-File "C:\Users\File4.csv"

File4.csv должно выглядеть так:

ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;

Может быть, есть другой способ достичь моей цели! Спасибо

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Если ваши файлы не слишком большие, вы можете сделать это с помощью простого ForEach-Object l oop:

$csv1   = Import-Csv -Path 'D:\Test\File1.csv' -Delimiter ';'
$result = Import-Csv -Path 'D:\Test\File2.csv' -Delimiter ';' | 
          ForEach-Object {
              $name = $_.Name
              $item = $csv1 | Where-Object { $_.Description -eq $name } | Select-Object -First 1
              # update the Name property and output the item
              if ($item) { 
                $_.Name = $item.NO
                # if you output the row here, the result wil NOT contain rows that did not match
                # $_   
              }
              # if on the other hand, you would like to retain the items that didn't match unaltered,
              # then output the current row here
              $_
          }

# output on screen
$result | Format-Table -AutoSize

#output to new CSV file
$result | Export-Csv -Path 'D:\Test\File4.csv' -Delimiter ';' -NoTypeInformation

Результат на экране:

ID     Name Status*                    Scheduled Start Date Actual Start Date Actual End Date Scheduled End Date SLA
--     ---- -------                    -------------------- ----------------- --------------- ------------------ ---
144862 L001 Scheduled                  1524031200                                             1524033000            
149137 L002 Implementation In Progress 1528588800                                             1548968400            
150564 L003 Scheduled                  1569456000                                             1569542400            
150564 L004 Scheduled                  1569456000                                             1569542400            
150564 L005
0 голосов
/ 23 апреля 2020

Вот один из подходов, который вы можете использовать:

  • Импортируйте оба CSV-файла с помощью Import-Csv
  • Создайте таблицу поиска ha sh из первого CSV-файл, где Description, которые вы хотите заменить, являются ключами, а NO - значениями.
  • Go через второй CSV-файл и заменяют любые значения из столбца Name из таблица ha sh, если ключ существует. Мы можем использовать System.Collections.Hashtable.ContainsKey, чтобы проверить, существует ли ключ. Это операция O(1) с постоянным временем, поэтому поиск выполняется быстро.
  • Затем мы можем экспортировать окончательный CSV с Export-Csv. Я использовал -UseQuotes Never, чтобы не выводить кавычки " в ваш выходной файл. Эта функция доступна только в PowerShell 7 . Для более ранних версий PowerShell вы можете взглянуть на Как удалить все кавычки в файле csv с помощью сценария powershell? , чтобы найти другие альтернативы удалению кавычек из файла CSV.

Демонстрация:

$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"

$ht = @{}
foreach ($item in $csvFile1) {
    if (-not [string]::IsNullOrEmpty($item.Description)) {
        $ht[$item.Description] = $item.NO
    }
}

& {
    foreach ($line in $csvFile2) {
        if ($ht.ContainsKey($line.Name)) {
            $line.Name = $ht[$line.Name]
        }
        $line
    }
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never

Или вместо переноса foreach l oop внутри блока скрипта с использованием Call Operator & , мы можем использовать Foreach-Object. Вы можете взглянуть на about_script_blocks для получения дополнительной информации о блоках скрипта.

$csvFile2 | ForEach-Object {
    if ($ht.ContainsKey($_.Name)) {
        $_.Name = $ht[$_.Name]
    }
    $_
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never

File4.csv

ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;

Обновление

Для обработки нескольких значений с одинаковыми Name, мы можем преобразовать вышеупомянутое, чтобы использовать таблицу ha sh System.Management.Automation.PSCustomObject, где у нас есть два свойства Count для отслеживания текущего элемента, который мы видим, и NO который представляет собой массив чисел:

$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"

$ht = @{}
foreach ($row in $csvFile1) {
    if (-not $ht.ContainsKey($row.Description) -and 
        -not [string]::IsNullOrEmpty($item.Description)) {
        $ht[$row.Description] = [PSCustomObject]@{
            Count = 0
            NO = @()
        }
    }
    $ht[$row.Description].NO += $row.NO
}

& {
    foreach ($line in $csvFile2) {
        if ($ht.ContainsKey($line.Name)) {
            $name = $line.Name
            $pos = $ht[$name].Count
            $line.Name = $ht[$name].NO[$pos]
            $ht[$name].Count += 1
        }
        $line
    }
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...