我试图让Powershell使用Regex验证电子邮件地址,并将电子邮件地址放入好的和坏的csv文件中。我可以让它跳过一行并写入文件,但无法让它定位电子邮件地址并验证它们,然后将行写入好的和坏的文件。我可以在C#和JavaScript中完成它,但从未在Powershell中完成它。我知道这可以做到,但不知道如何做。
这是我到目前为止所做的:
EXPLAIN SELECT ...
Function IsValidEmail {
Param ([string] $In)
# Returns true if In is in valid e-mail format.
[system.Text.RegularExpressions.Regex]::IsMatch($In,
"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|
(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
}
## Now we need to check the original file for invalid and valid emails.**
$list = Get-Content C:\Emails\OriginalEmails\emailAddresses.csv
# This way we also use the foreach loop.
##======= Test to see if the file exists ===========
if (!(Test-Path "C:\Emails\ValidEmails\ValidEmails.csv")) {
New-Item -path C:\Emails\ValidEmails -name ValidEmails.csv -type
"file" # -value "my new text"
Write-Host "Created new file and text content added"
}
else {
## Add-Content -path C:\Share\sample.txt -value "new text content"
Write-Host "File already exists and new text content added"
}
if (!(Test-Path "C:\Emails\InValidEmails\InValidEmails.csv")) {
New-Item -path C:\Emails\InValidEmails -name InValidEmails.csv -type
"file" # -value "my new text"
Write-Host "Created new file and text content added"
}
else {
# Add-Content -path C:\Emails\ValidEmails -value "new text content"
Write-Host "File already exists and new text content added"
}
#$Addresses = Import-Csv "C:\Data\Addresses.csv" -Header
Name, Address, PhoneNumber | Select -Skip 1
$EmailAddressImp = Import-Csv
"C:\Emails\OriginalEmails\emailAddresses.csv" -Header
FirstName, LastName, Email, Address, City, State, ZipCode | Select
FirstName, LastName, Email, Address, City, State, ZipCode -Skip 1
答案 0 :(得分:7)
我正在尝试让Powershell使用Regex验证电子邮件地址
我会建议不要这样做。使用正则表达式准确验证电子邮件地址可能比您想象的要困难得多。
让我们来看看你的正则表达式模式:
^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$
在它的当前表单中,它错误地验证了.@domain.tld
。
另一方面,它不会验证unicode编码的国际化域名,例如user@☎.com
(是的,这是一个有效的电子邮件地址)
我不会尝试查找或构建完美的电子邮件验证正则表达式模式,而是使用MailAddress
类进行验证:
function IsValidEmail {
param([string]$EmailAddress)
try {
$null = [mailaddress]$EmailAddress
return $true
}
catch {
return $false
}
}
如果输入字符串是有效的电子邮件地址,则转换为[mailaddress]
将成功,函数返回$true
- 否则,强制转换将导致异常,并返回{{1 }}
导出数据时,我会考虑在内存中一次性收集所有结果,然后在结束时将其写入文件一次。
如果您使用的是PowerShell版本2或3,则可以通过$false
的两次传递执行相同操作:
Where-Object
如果您使用的是PowerShell 4.0或更高版本,我建议您在$EmailAddresses = Import-Csv "C:\Emails\OriginalEmails\emailAddresses.csv" -Header FirstName, LastName, Email, Address, City, State, ZipCode | Select -Skip 1
$valid = $list |Where-Object {IsValidEmail $_.Email}
$invalid = $list |Where-Object {-not(IsValidEmail $_.Email)}
模式下使用.Where()
扩展程序:
Split
导出到文件之前:
$EmailAddresses = Import-Csv "C:\Emails\OriginalEmails\emailAddresses.csv" -Header FirstName, LastName, Email, Address, City, State, ZipCode | Select -Skip 1
$valid,$invalid = $list.Where({IsValidEmail $_.Email}, 'Split')
答案 1 :(得分:4)
您可以使用-match
运算符,而不是调用[Regex]
类。这是一个简单的例子,没有任何包装函数:
$EmailRegex = '^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$'
$EmailList = @('a@a.com', 'b@b.co', 'm.a@example.il')
foreach ($Email in $EmailList) {
$DidItMatch = $Email -match $EmailRegex
if ($DidItMatch) {
# It matched! Do something.
}
else {
# It didn't match
}
}
仅供参考,当您使用-match
运算符时,如果它返回布尔值$true
,则PowerShell会自动填充名为$matches
的内置(又称“自动”)变量。为避免意外行为,您可能希望在每次迭代期间将此变量重置为$null
,或者将其包装在函数中,就像在原始示例中一样。这将使变量作用域保持在函数级别,只要您不在其中一个父作用域中声明它。
验证完电子邮件地址后,您可以使用以下方法将其附加到现有的CSV文件中:
Export-Csv -Append -FilePath filepath.csv -InputObject $Email
为了提高可用文件系统资源的效率,您可能希望在将它们附加到目标CSV文件之前,在内存中缓冲一些电子邮件地址。
# Initialize a couple array buffers
$ValidEmails = @()
$InvalidEmails = @()
if ($ValidEmails.Count -gt 50) {
# Run the CSV export here
}
if ($Invalid.Count -gt $50) {
# Run the CSV export here
}
如果您需要进一步的帮助,请编辑您的问题并澄清哪些不适合您?
答案 2 :(得分:1)
当前的前2个答案中的每个都有一个明显的缺陷:
@Trevor的答案就可以了,除非您提供此答案:
John Doe <johndoe@somewhere.com>
@Mathias的答案是关于容纳特殊(至今有效)的地址,例如具有非ASCII或无TLD后缀的地址。以下地址全部通过[mailaddress]
强制转换成功验证:
olly@somewhere | olly@somewhere. | olly@somewhere...com etc
如果像我一样,您不会在电子邮件数据库中使用这些极端情况,那么两种想法的结合可能会更有用,就像这样:
function IsValidEmail {
param([string]$Email)
$Regex = '^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$'
try {
$obj = [mailaddress]$Email
if($obj.Address -match $Regex){
return $True
}
return $False
}
catch {
return $False
}
}
为可能很长的邮件列表中的每个电子邮件地址创建$obj
可能会带来性能开销。但是我想那是另一回事。
答案 3 :(得分:1)
您可以使用mailaddress
类型来确保它符合RFC,但是您可能仍要确保域有效:
Resolve-DnsName -Name ('vertigoray@example.com' -as [mailaddress]).Host -Type 'MX'
作为功能参数的验证脚本,效果很好:
function Assert-FromEmail {
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ Resolve-DnsName -Name $_.Host -Type 'MX' })]
[mailaddress]
$From
)
Write-Output $From
}
成功输出该函数的示例:
PS > Assert-FromEmail -From vertigoray@example.com
DisplayName User Host Address
----------- ---- ---- -------
vertigoray example.com vertigoray@example.com
在失败时输出该函数的示例:
PS > Assert-FromEmail -From vertigoray@example..com
Assert-FromEmail : Cannot validate argument on parameter 'From'. The " Resolve-DnsName -Name $_.Host -Type 'MX' "validation script for the argument with value "vertigoray@example..com" did not return a result of True. Determine why the validation script failed, and then try the command again.
At line:1 char:24
+ Assert-FromEmail -From vertigoray@example..com
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Assert-FromEmail], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Assert-FromEmail
答案 4 :(得分:0)
这是一个尝试我编写和测试的人,并且在迄今为止的任何环境中都没有让我失望。不,说它不会在其他人身上,但对我来说,它已经100%了。
$SomeEmailAddresses = @'
From:JoeBob@yahoo.com,Tom TheCat tcat@snailmail.net,jerry@snailmail.net
To:TulaJane@hotmail.com;JF@gmail.com;tiger@outlook.com;
Doug Tompson DTompson@icloud.com
MailTo:BobsYourUncle@protonmail.com;
johnny.bravo@yahoo.co.uk
'@
(((Select-String -InputObject $SomeEmailAddresses `
-Pattern '\w+@\w+\.\w+|\w+\.\w+@\w+\.\w+\.\w+' `
-AllMatches).Matches).Value)
Rsults
JoeBob@yahoo.com
tcat@snailmail.net
jerry@snailmail.net
TulaJane@hotmail.com
JF@gmail.com
tiger@outlook.com
DTompson@icloud.com
BobsYourUncle@protonmail.com
johnny.bravo@yahoo.co.uk