Скрипт для удаления строк на основе записей из указанного столбца c в файле CSV - PullRequest
1 голос
/ 28 марта 2020

У меня есть файл, структурированный таким образом (табуляция разделена):

HEADER_1    HEADER_2
entry_A     entry_A
entry_B     entry_C
entry_A     entry_D
entry_D     entry_A

Что мне нужно сделать, так это: каждый раз, когда запись из первого столбца появляется во втором столбце (в любой момент), удаляйте все строка, в которой появляется запись

Требуемый вывод:

HEADER_1    HEADER_2
entry_B     entry_C
entry_A     entry_D

Я пытался с Sort-Object -Unique, но вывод неправильный, он просто удаляет повторяющиеся строки

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Чтобы вывести строку, в которой Header_2 никогда не содержит записи из всех значений Header_1, вы можете сделать следующее:

Windows PowerShell:

$data = Import-Csv file.csv -Delimiter "`t"
($data | where Header_1 -notin $data.Header_2 |
    ConvertTo-Csv -NoType -Delimiter "`t") -replace '^"|"$|"(\t)"','$1' |
        Set-Content file.csv

PowerShell 7:

$data = Import-Csv file.csv -Delimiter "`t"
$data | where Header_1 -notin $data.Header_2 |
    Export-Csv -NoType -Delimiter "`t" -UseQuotes AsNeeded

Мне кажется, что вы хотите сделать, это вывести строки, в которых Header_2 еще не появился как значение Header_1, что означает, что вы игнорируете будущий Header_1 значения.

$list = [system.collections.generic.list[string]]@()
(Import-Csv file.csv -delimiter "`t" | Foreach-Object {
    $list.Add($_.Header_1)
    if ($_.Header_2 -notin $list) { 
        $_ 
    }
} | ConvertTo-Csv -NoType -Delimiter "`t") -replace '^"|"$|"(\t)"','$1' |
        Set-Content file.csv

Вы можете go маршрут без использования команд *-Csv, и тогда вам не придется иметь дело с соответствующим текстом для неосновных версий PowerShell.

$list = [system.collections.generic.list[string]]@()
Get-Content file.csv | Foreach-Object {
    $h1,$h2 = $_ -split '\t'
    $list.Add($h1)
    if ($h2 -notin $list) { 
        $_ 
    }
} | Set-Content file.csv
0 голосов
/ 29 марта 2020

Вы также можете использовать класс. NET System.Collections.Generic.HashSet для O (1) поиска с Contains():

$data = Import-Csv -Path file.csv -Delimiter "`t"

$hashSet = New-Object -TypeName System.Collections.Generic.HashSet[string]

$keep = @()
foreach ($row in $data) 
{
    $hashSet.Add($row.HEADER_1)
    if (-not($hashSet.Contains(($row.HEADER_2))))
    {
        $keep += $row
    }
}

$keep | Export-Csv -Path file.csv -Delimiter "`t" -NoTypeInformation

Какие результаты в новом file.csv:

"HEADER_1"  "HEADER_2"
"entry_B"   "entry_C"
"entry_A"   "entry_D"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...