1

我正在使用 Powershell 搜索一个大文件,以查找所有包含 mm-dd-yyyy 格式的字符串。然后我需要提取字符串以确定日期是否为有效日期。该脚本在大多数情况下都有效,但返回的结果太多,并且没有提供我想要的所有信息。文件中有像 012-34-5678 这样的字符串,为此我会失败,并且 12-34-5678 的值将作为无效日期返回。我也无法返回发现无效日期的行号。有人可以看看我下面的脚本,看看我做错了什么吗?

被注释掉的两行将返回字符串编号和在该行中找到的整个字符串,但我不知道如何仅从该行中获取 mm-dd-yyyy 部分并确定它是否是有效日期。

任何帮助将不胜感激。谢谢。

#$matches = Select-String -Pattern $regex -AllMatches -Path "TestFile_2013_01_06.xml" | 

#$matches | Select LineNumber,Line


$regex = "\d{2}-\d{2}-\d{4}"     

$matches = Select-String -Pattern $regex -AllMatches -Path "TestFile_2013_01_06.xml" |
   Foreach {$_.Matches | Foreach {$_.Groups[0] | Foreach {$_.Value}}}

foreach ($match in $matches) {

    #$date = [datetime]::parseexact($match,"MM-dd-yyyy",$null)  

    if (([Boolean]($match -as [DateTime]) -eq $false ) -or ([datetime]::parseexact($match,"MM-dd-yyyy",$null).Year -lt "1800")) {
        write-host "Failed $match"
    }
}
4

3 回答 3

5

您可以在正则表达式本身中进行大量验证,使其更加健壮:

$regex = "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)[0-9]{2}"

上述匹配任何介于 1900 年 1 月 1 日到 2099 年 12 月 31 日之间的日期,并接受正斜杠、破折号、空格和圆点作为日期分隔符。它不拒绝无效日期,例如 2 月 30 日或 31 日、11 月 31 日等。

于 2013-01-25T15:57:28.837 回答
2

行号在 Select-String 输出的对象上可用,但您没有在 $matches 中捕获它。尝试这个:

$matchInfos = @(Select-String -Pattern $regex -AllMatches -Path "TestFile_2013_01_06.xml")
foreach ($minfo in $matchInfos)
{
    #"LineNumber $($minfo.LineNumber)"
    foreach ($match in @($minfo.Matches | Foreach {$_.Groups[0].value}))
    {
        if ($match -isnot [DateTime]) -or 
            ([datetime]::parseexact($match,"MM-dd-yyyy",$null).Year -lt "1800")) {
          Write-host "Failed $match on line $($minfo.LineNumber)"
        }
    }
 }
于 2013-01-25T15:57:37.660 回答
0

我可能只是尝试将 Select-String 的结果与实际匹配项联系起来。我没有包括检查日期是否足够“新”的条件:

Select-String -Pattern '\d{2}-\d{2}-\d{4}' -Path TestFile_2013_01_06.xml -AllMatches | 
    ForEach-Object {
        $Info = $_ | 
            Add-Member -MemberType NoteProperty -Name Date -Value $null -PassThru |
            Add-Member -MemberType NoteProperty -Name Captured -Value $null -PassThru
        foreach ($Match in $_.Matches) {
            try {
                $Date = [DateTime]::ParseExact($Match.Value,'MM-dd-yyyy',$null)
            } catch {
                $Date = 'NotValid'
            } finally {
                $Info.Date = $Date
                $Info.Captured = $Match.Value
                $Info
            }
        }
    } | Select Line, LineNumber, Date, Captured

当我对一些示例数据进行尝试时,我得到了这样的结果:

Line                                  LineNumber Date                Captured  
----                                  ---------- ----                --------  
Test 12-12-2012                                1 2012-12-12 00:00:00 12-12-2012
Test another 12-40-2030                        2 NotValid            12-40-2030
20-20-2020 And yet another 01-01-1999          3 NotValid            20-20-2020
20-20-2020 And yet another 01-01-1999          3 1999-01-01 00:00:00 01-01-1999
于 2013-01-25T20:14:47.887 回答