String 将电子邮件字符串转换为.csv列

String 将电子邮件字符串转换为.csv列,string,powershell,csv,type-conversion,String,Powershell,Csv,Type Conversion,我有一个巨大的.txt文件,里面充满了这种格式的电子邮件: 多伊,约翰,男;史密斯,简,男 我想知道是否有办法将这个.txt文件转换成一个.csv文件,该文件有两列:一列用于名称,一列用于电子邮件: 第1栏: 多伊,约翰,男 史密斯,简,我是女性 第2栏: JohnD@email.com JaneS@email.com 我有点不知所措如何开始这个,我知道名称中的逗号使这有点复杂。感谢您的任何帮助电子邮件中没有空格,所以类似这样的内容 $content = "Doe, John L (M

我有一个巨大的.txt文件,里面充满了这种格式的电子邮件:

多伊,约翰,男;史密斯,简,男

我想知道是否有办法将这个.txt文件转换成一个.csv文件,该文件有两列:一列用于名称,一列用于电子邮件:

第1栏:

多伊,约翰,男

史密斯,简,我是女性

第2栏:

JohnD@email.com

JaneS@email.com


我有点不知所措如何开始这个,我知道名称中的逗号使这有点复杂。感谢您的任何帮助

电子邮件中没有空格,所以类似这样的内容

$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"
$content.Split(";") | % { $_.Trim() } | ? { $_ } | % { 
    $iSpace = $_.LastIndexOf(" "); [PSCustomObject]@{ Name = $_.Substring(0, $iSpace) ; Email = $_.Substring($iSpace+2).TrimEnd(">")
} } | ConvertTo-Csv

在这里,正则表达式可能是最简单的方法。问题是格式可能会有很大差异

$EmailAddresses = 'Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;'

$EmailAddresses -split ';' |
    Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
    ForEach-Object {
        if ($_ -match '\s*(?<Name>.*?)\s*<(?<Email>.*)>\s*') {
            [PSCustomObject]@{Name = $Matches['Name']; Email = $Matches['Email'] }
        }
        else {
            Write-Warning "Unrecognized name and email in '$_'"
        }
    } |
    Export-Csv $ExportFile -NoTypeInformation
这将解析您的内容并创建一个包含两列的CSV文件。它将对任何它不理解的条目发出警告,尽管它将忽略任何仅为空白的条目

下面是对正则表达式的解释:

'\s*(?<Name>.*?)\s*<(?<Email>.*)>\s*'
\s*:零个或多个空白字符 ?.*:已命名的捕获组“Name”,其中包含一定数量的任意字符 \s*:零个或多个空白字符 \s*:零个或多个空白字符


另一个选项是拆分字符串并将每个字符串转换为System.Net.Mail.MailAddress,该系统具有Address和DisplayName属性。那可能效果最好,但上次我试的时候遇到了麻烦。不幸的是,我不记得是什么问题。我认为显示名称中的逗号有点不合适。

下面是一个用正则表达式将文件解析为psobject,然后像往常一样导出为CSV的示例

$In = 'Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;' #use get-content here
$SplitInput = $In -split ';' | Where-Object {$_ -ne ''} #filter in case of extra ; at start or end as in example

$Users = $SplitInput | ForEach-Object {
    $_ -match '^\s*(?<Name>.*) <(?<Email>.*)>$' | Out-Null
    New-Object PSCustomObject @{
        Name = $Matches.Name
        Email = $Matches.Email
    }
}

所用正则表达式的详细信息-

您可以执行以下操作:

# Get file contents as string
$fileContents = Get-Content -Path .\sample.txt -Raw

# Split on ; to get each user
# Remove empty entries and trim also
$users = $fileContents.Split(';', [System.StringSplitOptions]::RemoveEmptyEntries).Trim()

# Export each user to CSV file inside this scriptblock
& {
    foreach ($user in $users) {

        # Get index of last space
        $splitIndex = $user.LastIndexOf(' ')
    
        # Create PSCustomObject with Name and Email
        # We can substring this with above split index
        [PSCustomObject]@{
            Name = $user.Substring(0, $splitIndex).Trim()
            Email = $user.Substring($splitIndex + 1).Trim('<', '>')
        }
    }
} | Export-Csv -Path .\sample.csv -NoTypeInformation

运行@Bacon Bits提供的以下命令:

$content = Get-content -Path 'C:\.....txt'

$content -split ';' |
    Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
    ForEach-Object {
        if ($_ -match '\s*(?<Name>.*?)\s*<(?<Email>.*)>\s*') {
            [PSCustomObject]@{Name = $Matches['Name']; Email = $Matches['Email'] }
        }
        else {
            Write-Warning "Unrecognized name and email in '$_'"
        }
    } | Export-Csv -Path 'C:\.....csv' -NoTypeInformation

很多很棒的答案。我想添加另一个选项

$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"

switch -Regex ($content -split ';'){
    '\s?(.+)\s<(.+)>' {
        [PSCustomObject]@{
            Name  = $Matches.1
            Email = $Matches.2
        }
    }
}
要导出csv,只需将输出捕获到一个变量,或者可以使用子表达式将其包围,然后使用管道

$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"

$output = switch -Regex ($content -split ';'){
    '\s?(.+)\s<(.+)>' {
        [PSCustomObject]@{
            Name  = $Matches.1
            Email = $Matches.2
        }
    }
}

$output | Export-Csv $outputfile -NoTypeInformation


文本文件中是否只有一行,或者信息被拆分为多行?不幸的是,只有一行。这样做很好,但在运行itI时留下了<或>,我想我错过了一次编辑,因为内容是复制/粘贴的。我改变了答案。很好的正则表达式示例,这很有效!另一个很好的正则表达式示例,我很欣赏它的分解和添加的警告功能。非常感谢。
$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"

switch -Regex ($content -split ';'){
    '\s?(.+)\s<(.+)>' {
        [PSCustomObject]@{
            Name  = $Matches.1
            Email = $Matches.2
        }
    }
}
Name                   Email          
----                   -----          
Doe, John L (Male)     JohnD@email.com
Smith, Jane M (Female) JaneS@email.com
$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"

$output = switch -Regex ($content -split ';'){
    '\s?(.+)\s<(.+)>' {
        [PSCustomObject]@{
            Name  = $Matches.1
            Email = $Matches.2
        }
    }
}

$output | Export-Csv $outputfile -NoTypeInformation
$content = "Doe, John L (Male) <JohnD@email.com>; Smith, Jane M (Female) <JaneS@email.com>;"

$(switch -Regex ($content -split ';'){
    '\s?(.+)\s<(.+)>' {
        [PSCustomObject]@{
            Name  = $Matches.1
            Email = $Matches.2
        }
    }
}) | Export-Csv $outputfile -NoTypeInformation