PowerShell: список строк файла CSV, в которых хотя бы одно значение между 3-м и последним столбцом равно «0» или «1» - PullRequest
1 голос
/ 24 октября 2019

В моем скрипте PowerShell я работаю с CSV-файлом, который выглядит следующим образом (с количеством строк и столбцов, которые могут различаться, но всегда будут хотя бы заголовки и первые 2 столбца):

OS;IP;user0;user1;user3
Windows;10.0.0.1;;;
Linux;hostname2;0;;1
Linux;10.0.0.3;;0;0
Linux;hostname4;;;
Windows;hostname5;1;1;1

Я в основном перечисляю серверы в первом столбце и пользователей в первом ряду (заголовок CSV). Это представляет пользовательскую матрицу «предоставления доступа» серверам (1 для «дать доступ», 0 для «удалить доступ» и пустое для «не изменять»).

Я ищу способизвлечь только те строки, которые содержат значение, равное «1» или «0», между (и включая) 3-м и последним столбцом. (= чтобы в конечном итоге получить список серверов, где должны быть изменены права доступа)

Итак, взяв приведенный выше пример, я хочу только вернуть следующие строки:

Linux;hostname2;0;;1
Linux;10.0.0.3;;0;0
Windows;hostname5;1;1;1

Любые подсказки, чтобы сделать этовозможно? Или наоборот (получить те, у которых нет 0 или 1)? Даже если это означает использование «Get-Content» вместо «Import-CSV». Мне плевать на 1-й (заголовок) ряд;Я знаю, как это исключить.

Спасибо!

--- Окончательное решение, благодаря ответу @ Томалака:

$AccessMatrix = Import-CSV $CSVfile -delimiter ';'
$columns = $AccessMatrix | Get-Member -MemberType NoteProperty | Select-Object -Skip 2 -ExpandProperty Name
$AccessMatrix = $AccessMatrix | ForEach-Object {
    $row = $_
    foreach ($col in $columns) {
        if ($row.$col.trim() -eq "1" -OR $row.$col.trim() -eq "0") {
            $row         # this pushes the $row onto the pipeline
            break
        }
    }
}

1 Ответ

1 голос
/ 24 октября 2019

Далее используется Get-Member для выбора имен всех столбцов после первых двух.

Затем, используя ForEach-Object, мы можем вывести только те строки, которые имеют значение в любом из этих столбцов.

$data = ConvertFrom-Csv "OS;IP;user0;user1;user3
Windows;10.0.0.1;;;
Linux;hostname2;0;;1
Linux;10.0.0.3;;0;0
Linux;hostname4;;;
Windows;hostname5;1;1;1" -Delimiter ";"

$columns = $data | Get-Member -MemberType NoteProperty | Select-Object -Skip 2 -ExpandProperty Name

$data | ForEach-Object {
    $row = $_
    foreach ($col in $columns) {
        if ($row.$col -ne "") {
            $row         # this pushes the $row onto the pipeline
            break
        }
    }
}

Оператор break останавливает выполнение внутреннего цикла foreach, поскольку нет смысла в дальнейшей проверке, как только будет найден первый столбец с любым значением.

Это эквивалентно приведенному выше, если вы предпочитаете Where-Object:

$data | Where-Object {
    $row = $_
    foreach ($col in $columns) {
        if ($row.$col -ne "") {
            return $true
        }
    }
}
...