Формат CSV из объекта - PullRequest
       23

Формат CSV из объекта

0 голосов
/ 09 февраля 2019

Я пытаюсь выяснить, как создать .csv из объекта PowerShell с соответствующими столбцами.Я хочу создать CSV-файл с тремя столбцами (идентификатор пользователя, страна, количество).Также необходимо выполнить сортировку по идентификатору пользователя, а затем по стране (от А до Я).В приведенном ниже примере кода я хочу, чтобы вывод был таким:

User ID, Country, Count
Bob, China, 2
Joe, Canada, 1
Joe, United States, 1

$path = "C:\test\test.csv"
Set-Content -Path $path -Value “UserId, Country”
Add-Content -Path $path -Value "Joe, United States", "Bob, China", "Bob, China", "Joe, Canada"
(Import-Csv -Path $path) | Group-Object -Property UserID, Country -NoElement | Select-Object * -ExcludeProperty Values, Group | Select-Object @{Name="User ID, Country";Expression={$_.Name}}, Count | Export-Csv -Path $path -NoTypeInformation -Force
Get-Content -Path $path

К сожалению, когда я запускаю это, ID пользователя и Страна находятся в одном столбце, как показано ниже:

"User ID, Country","Count"
"Joe, United States","1"
"Bob, China","2"
"Joe, Canada","1"

Я считаю, что проблема связана с Select-Object @{Name="User ID, Country";Expression={$_.Name}}.Как я могу получить это в трех столбцах, отсортированных в соответствии с просьбой выше?В некотором смысле, я не совсем понимаю синтаксис кода проблемы.Если бы вы могли объяснить, что делает @{Name="User ID, Country";Expression={$_.Name}}, я был бы признателен.

РЕДАКТИРОВАТЬ Вот мой действительный код на случай, если это вообще поможет с проблемой.

Set-ExecutionPolicy RemoteSigned

$lastMonth = (get-date).AddMonths(-1)
$startDate = get-date -year $lastMonth.Year -month $lastMonth.Month -day 1
$endDate = ($startDate).AddMonths(1).AddSeconds(-1)
$operation = UserLoginFailed
$path = "C:\Failed Logins $($lastMonth.ToString("yyyy_MM")).csv"

Set-Content -Path $path -Value “UserId, Country”
Function Connect-EXOnline {
    $credentials = Get-Credential -Credential $credential     
    $Session = New-PSSession -ConnectionUri https://outlook.office365.com/powershell-liveid/ `
        -ConfigurationName Microsoft.Exchange -Credential $credentials `
        -Authentication Basic -AllowRedirection
    Import-PSSession $Session -AllowClobber
}
$credential = Get-Credential
Connect-EXOnline

$Logs = @()
do {
    $logs += Search-unifiedAuditLog -SessionCommand ReturnLargeSet -SessionId "UALSearch" -ResultSize 5000 -StartDate $startDate -EndDate $endDate -Operations $operation
}while ($Logs.count % 5000 -eq 0 -and $logs.count -ne 0)
 
$userIds = $logs.userIds | Sort-Object -Unique
 
foreach ($userId in $userIds) {
    $ips = @()
    $searchResult = ($logs | Where-Object {$_.userIds -contains $userId}).auditdata | ConvertFrom-Json -ErrorAction SilentlyContinue 
    $ips = $searchResult.clientip
    foreach ($ip in $ips) {
        $mergedObject = @{}
        $singleResult = $searchResult | Where-Object {$_.clientip -contains $ip} | Select-Object -First 1
        Start-sleep -m 400
        $ipresult = Invoke-restmethod -method get -uri http://ip-api.com/json/$ip
        $UserAgent = $singleResult.extendedproperties.value[0]
        $singleResultProperties = $singleResult | Get-Member -MemberType NoteProperty
        foreach ($property in $singleResultProperties) {
            if ($property.Definition -match "object") {
                $string = $singleResult.($property.Name) | ConvertTo-Json -Depth 10
                $mergedObject | Add-Member -Name $property.Name -Value $string -MemberType NoteProperty    
            }
            else {$mergedObject | Add-Member -Name $property.Name -Value $singleResult.($property.Name) -MemberType NoteProperty}          
        }
        $property = $null
        $ipProperties = $ipresult | get-member -MemberType NoteProperty
 
        foreach ($property in $ipProperties) {
            $mergedObject | Add-Member -Name $property.Name -Value $ipresult.($property.Name) -MemberType NoteProperty
        }
        $mergedObject | Select-Object UserId, Country  | Export-Csv $path -Append -NoTypeInformation
    }
}

(Import-Csv -Path $path) | Group-Object -Property UserID, Country -NoElement | Select-Object * -ExcludeProperty Values, Group | Select-Object @{Name="User ID, Country";Expression={$_.Name}}, Count | Export-Csv -Path $path -NoTypeInformation

По сути, у меня будет файл .csv, который содержит несколько адресов электронной почты и неудачных попыток входа по стране.Последняя строка используется для подсчета количества неудачных попыток каждого адреса электронной почты от каждой компании.Вот где проблема.

Ответы [ 3 ]

0 голосов
/ 10 февраля 2019

Я упростил вашу формулировку проблемы, чтобы решить одну проблему за один раз.
Я решил решить простую задачу создания выходного CSV-файла, который вы хотите, из указанного вами входного CSV-файла.Я создал входной файл с помощью блокнота, а не с PowerShell.

Вот что я придумал:

<# Summarizes log by user and country.   #>

Import-csv logfile.csv |
    Sort-Object  UserID, Country |
    Group-Object UserID, Country | 
    foreach { $b = $_.name -split ', '
        [PSCustomobject] @{UserID = $b[0]; Country= $b[1]; Count=$_.count}}|
    Export-Csv summary.csv

Import-Csv logfile.csv | Format-table
Import-Csv summary.csv | Format-table

Последние два шага просто отображают входной и выходной файлы CSV.Вот как это выглядело, когда я запускал его.

UserID Country      
------ -------      
Joe    United States
Bob    China        
Bob    China        
Joe    Canada       



UserID Country       Count
------ -------       -----
Bob    China         2    
Joe    Canada        1    
Joe    United States 1    
0 голосов
/ 10 февраля 2019

Как уже упоминалось в моем комментарии, вам понадобится два вычисленных свойства, чтобы снова разделить Имя.

(Import-Csv $path) | Group-Object 'User ID',Country -NoElement | 
    Select-Object @{n='UserID';e={($_.Name -split ', ')[0]}},
                  @{n='Country';e={($_.Name -split ', ')[1]}},
                  Count | Export-Csv $Path -NoTypeInformation

Это даст тот же результат, что и решение Уолтера Митти.

0 голосов
/ 09 февраля 2019

Вы можете значительно упростить свою жизнь, если используете доступные встроенные командлеты для данных CSV, например:

$path = 'C:\test\test.csv'
$Data = @'
UserID,Country,Count
Bob,China,2
Joe,Canada,1
Joe,United States,1
'@

ConvertFrom-Csv -Delimiter ',' -InputObject $Data -OutVariable CSVData
$CSVData | Export-Csv -Path $path -NoTypeInformation -Delimiter ','

Вы просто создаете свои данные по мере необходимости и конвертируете или экспортируете ихв один раз.

...