1

私はPowershellを使用して大きなファイルを検索し、mm-dd-yyyy形式の文字列をすべて含むすべての文字列を見つけています。次に、文字列を抽出して、日付が有効な日付であるかどうかを判断する必要があります。スクリプトはほとんどの部分で機能しますが、返される結果が多すぎて、必要なすべての情報が提供されません。ファイルには012-34-5678のような文字列があり、このために失敗し、12-34-5678の値が無効な日付として返されます。また、無効な日付が見つかった行番号を返すこともできません。誰かが以下の私のスクリプトを見て、私が間違っている可能性があることを確認できますか?

コメントアウトされた2行は、文字列番号とその行で見つかった文字列全体を返しますが、行から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 に答える