0

我试图弄清楚如何从具有适当列的 PowerShell 对象创建 .csv。我想创建一个包含三列(用户 ID、国家/地区、计数)的 .csv 文件。它还需要先按用户 ID 排序,然后按国家/地区(A 到 Z)。在下面的示例代码中,我希望输出如下所示:

用户 ID、国家、计数
鲍勃,中国,2
乔,加拿大,1
乔,美国,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 和国家/地区位于以下同一列中:

“用户 ID,国家/地区”,“计数”
"乔,美国","1"
“鲍勃,中国”,“2”
"乔,加拿大","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 文件,其中包含一堆电子邮件地址和按国家/地区分类的失败登录尝试。最后一行用于计算每个电子邮件地址从每个公司收到的失败尝试次数。这就是问题所在。

4

3 回答 3

1

我已经简化了您的问题陈述,以便一次解决一个问题。
我着手解决从您声明的输入 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    
于 2019-02-10T14:13:26.890 回答
0

正如我在评论中提到的,您需要两个计算属性来再次拆分名称。

(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

这将产生与 Walter Mitty 的解决方案相同的输出。

于 2019-02-10T19:47:14.267 回答
-1

当您为 CSV 数据使用内置的可用 cmdlet 时,您的生活会变得更轻松,如下所示:

$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 ','

您只需完全根据需要构建数据,然后一次转换或导出。

于 2019-02-09T14:39:53.090 回答