specific text of today's date from txt file by powershell

前端 未结 4 595
温柔的废话
温柔的废话 2021-01-28 08:45

I have a text file. Similar to this.

This is a sample data.
This is a sample data.
This is a sample data.
Sat Jun 06 08:17:01 2015
WARNING: Cannot delete file.
E         


        
相关标签:
4条回答
  • 2021-01-28 09:14

    $curdate is a string with the format ddMMyyyy, whereas the string in the log file containing the date is in the format ffffd MMM dd HH:mm:ss yyyy, which I assume to be the current locale, hence your use of Get-Date -UFormat %c.

    Therefore, your if($_ -eq $curdate) statement won't work.

    if($_ -eq $cur_date1) will return true if the timestamp contained in $_ represents the exact second your script starts running, but the subsequent Where-Object statement won't evaluate to $true (since $_ is currently referring to the line with the date, not the error) and even if it did, wouldn't return anything (you haven't piped anything to Where-Object or specified an InputObject parameter argument)

    As a general rule, for date comparison, don't use a string representation, use the Date property of the datetime objects you are comparing.

    Wrong/frail approach:

    Get-ChildItem |Where-Object { $_.LastWriteTime.ToString("ddMMyyyy") -eq $datestring }
    

    Safe approach:

    $today = (Get-Date).Date
    Get-ChildItem |Where-Object { $_.LastWriteTime.Date -eq $today }
    

    If you want to extract the preceding date of an error message, the easiest way is to use Select-String with the Context parameter:

    Select-String -Path C:\samplefile.log -Pattern "^Error" -Context 2 | Select-Object -First 1
    
      C:\samplefile.log:4:Sat Jun 06 08:17:01 2015
      C:\samplefile.log:5:WARNING: Cannot delete file.
    > C:\samplefile.log:6:Error-101
      C:\samplefile.log:7:This is a sample data.
      C:\samplefile.log:8:This is a sample data.
    

    You can then use the output data from Select-String to grab and compare the date:

    $Today  = (Get-Date).Date
    $Format = 'ffffd MMM dd HH:mm:ss yyyy'
    Select-String -Path C:\samplefile.log -Pattern '^Error' -Context 2 | Where-Object {
        [DateTime]::ParseExact($_.Context.PreContext[0],$Format,$null).Date -eq $Today
    } | Select-Object @{Name="Error";Expression={$_.Line}},@{Name="Date";Expression={[DateTime]::ParseExact($_.Context.PreContext[0],$Format,$null).ToString("ddMMyyyy")}}
    
    0 讨论(0)
  • 2021-01-28 09:26

    While you parse error*.txt file, you can save last seen date in a variable. So, when you encounter Error-* record, you will know to what date it related to.

    $Today=[datetime]::Today
    Get-Content D:\Script\system.txt|
    ForEach-Object {
        $System=$_
        Get-ChildItem -Path "filesystem::\\$System\D$\Error" -Filter error*.txt|
        # filesystem:: allows code to work, even if current provider is not a filesystem provider.
        Where-Object {$_.LastWriteTime.Date-eq$Today}|
        ForEach-Object {
            Get-Content -LiteralPath $_.PSPath|
            ForEach-Object {
                $ParseDate=New-Object datetime
                $LastSeenDate=$null
            } {
                if([datetime]::TryParseExact($_,'ffffd MMM dd HH:mm:ss yyyy',[cultureinfo]::InvariantCulture,'None',[ref]$ParseDate)){
                    $LastSeenDate=$ParseDate
                }
                if($_.StartsWith('Error-')){
                    [PSCustomObject]@{
                        Error=$_
                        Date=$LastSeenDate
                        System=$System
                    }
                }
            }
        }
    }|
    Where-Object {$_.Date.Date-eq$Today}
    
    0 讨论(0)
  • 2021-01-28 09:28

    I got pinged to the question, so here's my take on a solution:

    #Create test file from posted data:
    (@'
    This is a sample data.
    This is a sample data.
    This is a sample data.
    Sat Jun 06 08:17:01 2015
    WARNING: Cannot delete file.
    Error-101
    Error-100
    Error-102
    This is a sample data.
    This is a sample data.
    Error-10666
    This is a sample data.
    Sat Jun 06 10:17:01 2015
    File deleted.
    This is a sample data.
    This is a sample data.
    Sat Jun 06 10:17:01 2015
    File deleted.
    Sat Jun 06 11:17:01 2015
    WARNING: Cannot delete file.
    Error-101
    This is a sample data.
    Sat Jun 06 18:17:01 2015
    WARNING: Cannot delete file.
    Error-101
    This is a sample data.
    '@).split("`n") |
    #where { -notmatch '^#'} |
    foreach {$_.trim()} |sc testfile.txt
    
    #Proxy function for testing
    function get-date {[datetime]'06/06/2015 18:17:01'} 
    
    #Actual solution code follows:
    
    $DateSearch = (get-date).ToString('MMM dd [0-9:]+ yyyy(.+)')
    $DateSearch = '(?ms)' + $DateSearch
    
    if ((Get-Content testfile.txt -Raw) -match  $DateSearch)
    { $Matches[1].Split("`n") -like 'Error*' }
    
    #remove the proxy function:
     remove-item function:get-date
    
    Error-101
    Error-100
    Error-102
    Error-10666
    Error-101
    Error-101
    

    This uses the [datetime] tostring() method to help create a regex to search for today's date in the file. Then it captures everything from that point to the end of the file, splits it at the newlines and filters out everything except the Error records.

    Ignore that proxy function for get-date. That's just there to get the script to work with the test data.

    0 讨论(0)
  • 2021-01-28 09:31

    You can try converting each line to a datetime. That's not a standard date format, however, so [datetime]::TryParse() isn't likely to work. That means you'll need to use [datetime]::TryParseExact(), which is moderately more irritating because you have to give it a provider and a style, even though you're probably not using either.

    $dateString = 'Sat Jun 06 08:17:01 2015';
    
    [System.Globalization.CultureInfo]$provider = [System.Globalization.CultureInfo]::InvariantCulture;
    [System.Globalization.DateTimeStyles]$style = [System.Globalization.DateTimeStyles]::None;
    
    $format = "ffffd MMM dd HH:mm:ss yyyy";
    [ref]$parsedDate = get-date;
    [DateTime]::TryParseExact($dateString, $format, $provider, $style, $parsedDate);
    $parsedDate.Value;
    

    A key thing to note is that both TryParse() and TryParseExact() don't return values; they return True when the parsing is successful, and False when it fails. In order to pass the result, you pass a variable by reference and the function modifies the referenced variable. $parsedDate.Value is where the actual datetime value is because $parsedDate itself is a reference (pointer).

    If the function fails and returns false, $parsedDate will have a value of [datetime]::MinValue (Jan 1, 0001).

    0 讨论(0)
提交回复
热议问题