powershell 从 txt 文件中获取今天日期的特定文本
specific text of today's date from txt file by powershell
我有一个文本文件。类似这样。
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.
此文件包含一个月的数据。
一个目录中可能有多个这样的文件。脚本需要检查今天修改的文件。
我想获取今天日期的 Error-???(整行错误-)值。
到目前为止,我已经创建了这个。
$cur_date1 = get-date -UFormat %c
$curdate = (get-date).ToString("ddMMyyyy")
ForEach ($system in (Get-Content D:\Script\system.txt)) {
$dir = "\$system\D$\Error\"
$latest = Get-ChildItem -Path $dir -Filter error*.txt | where{$_.LastWriteTime.ToString("ddMMyyyy") -eq $date }
$files=$latest.name
Foreach($file in $files){
$path= $dir+$file
$search = Get-Content $path
$a = $search| if($_ -eq $curdate){
Where-Object{$_.Contains("Error-") }
}
}
}
我可以查看今天创建的文件。
我可以获得整个文件的内容。
我可以搜索错误字符串,但无法搜索当前日期。
任何人都可以就此提出建议吗?
谢谢。
如果需要对标题或说明进行任何更改,请进行更改。
谢谢你的时间。
更新
特此通知您我的系统日期时间格式如下。
dd/mm/yyyyhh:mm:ss
您可以尝试将每一行转换为日期时间。但是,这不是标准的日期格式,因此 [datetime]::TryParse()
不太可能起作用。这意味着您将需要使用 [datetime]::TryParseExact()
,这有点让人恼火,因为您必须给它一个提供者和一种样式,即使您可能没有使用任何一个。
$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 = "ddd MMM dd HH:mm:ss yyyy";
[ref]$parsedDate = get-date;
[DateTime]::TryParseExact($dateString, $format, $provider, $style, $parsedDate);
$parsedDate.Value;
需要注意的一个关键点是 TryParse()
和 TryParseExact()
都不是 return 值;他们 return 解析成功时为真,失败时为假。为了传递结果,您通过引用传递一个变量,函数修改引用的变量。 $parsedDate.Value
是实际日期时间值所在的位置,因为 $parsedDate
本身就是一个引用(指针)。
如果函数失败并且 return 为假,$parsedDate
的值将是 [datetime]::MinValue
(0001 年 1 月 1 日)。
$curdate
是格式为 ddMMyyyy
的字符串,而日志文件中包含日期的字符串格式为 ddd MMM dd HH:mm:ss yyyy
,我假设这是当前语言环境,因此您使用 Get-Date -UFormat %c
.
因此,您的 if($_ -eq $curdate)
语句将不起作用。
if($_ -eq $cur_date1)
will return 如果 $_
中包含的时间戳表示脚本开始的确切秒数 运行,则为真但是随后的 Where-Object
语句不会计算为 $true
(因为 $_
当前指的是带有日期的行,而不是错误),即使它计算了,也不会 return 任何东西(你没有将任何东西传送到 Where-Object
或指定一个 InputObject
参数参数)
作为一般规则,对于日期比较,不要使用字符串表示,使用您正在比较的日期时间对象的 Date
属性。
Wrong/frail方法:
Get-ChildItem |Where-Object { $_.LastWriteTime.ToString("ddMMyyyy") -eq $datestring }
安全方法:
$today = (Get-Date).Date
Get-ChildItem |Where-Object { $_.LastWriteTime.Date -eq $today }
如果要提取错误消息的前一个日期,最简单的方法是使用 Select-String
和 Context
参数:
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.
然后您可以使用 Select-String
的输出数据来获取和比较日期:
$Today = (Get-Date).Date
$Format = 'ddd 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")}}
当您解析 error*.txt
文件时,您可以将上次查看日期保存在变量中。所以,当你遇到Error-*
记录时,你就会知道它与什么日期有关。
$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($_,'ddd 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}
我收到了这个问题的回复,所以这是我的解决方案:
#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
这使用 [datetime] tostring()
方法来帮助创建一个正则表达式来搜索文件中的今天日期。然后它捕获从该点到文件末尾的所有内容,在换行符处将其拆分并过滤掉除错误记录之外的所有内容。
忽略获取日期的代理函数。这只是为了让脚本与测试数据一起工作。
我有一个文本文件。类似这样。
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.
此文件包含一个月的数据。 一个目录中可能有多个这样的文件。脚本需要检查今天修改的文件。
我想获取今天日期的 Error-???(整行错误-)值。 到目前为止,我已经创建了这个。
$cur_date1 = get-date -UFormat %c
$curdate = (get-date).ToString("ddMMyyyy")
ForEach ($system in (Get-Content D:\Script\system.txt)) {
$dir = "\$system\D$\Error\"
$latest = Get-ChildItem -Path $dir -Filter error*.txt | where{$_.LastWriteTime.ToString("ddMMyyyy") -eq $date }
$files=$latest.name
Foreach($file in $files){
$path= $dir+$file
$search = Get-Content $path
$a = $search| if($_ -eq $curdate){
Where-Object{$_.Contains("Error-") }
}
}
}
我可以查看今天创建的文件。 我可以获得整个文件的内容。 我可以搜索错误字符串,但无法搜索当前日期。
任何人都可以就此提出建议吗?
谢谢。
如果需要对标题或说明进行任何更改,请进行更改。 谢谢你的时间。
更新
特此通知您我的系统日期时间格式如下。 dd/mm/yyyyhh:mm:ss
您可以尝试将每一行转换为日期时间。但是,这不是标准的日期格式,因此 [datetime]::TryParse()
不太可能起作用。这意味着您将需要使用 [datetime]::TryParseExact()
,这有点让人恼火,因为您必须给它一个提供者和一种样式,即使您可能没有使用任何一个。
$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 = "ddd MMM dd HH:mm:ss yyyy";
[ref]$parsedDate = get-date;
[DateTime]::TryParseExact($dateString, $format, $provider, $style, $parsedDate);
$parsedDate.Value;
需要注意的一个关键点是 TryParse()
和 TryParseExact()
都不是 return 值;他们 return 解析成功时为真,失败时为假。为了传递结果,您通过引用传递一个变量,函数修改引用的变量。 $parsedDate.Value
是实际日期时间值所在的位置,因为 $parsedDate
本身就是一个引用(指针)。
如果函数失败并且 return 为假,$parsedDate
的值将是 [datetime]::MinValue
(0001 年 1 月 1 日)。
$curdate
是格式为 ddMMyyyy
的字符串,而日志文件中包含日期的字符串格式为 ddd MMM dd HH:mm:ss yyyy
,我假设这是当前语言环境,因此您使用 Get-Date -UFormat %c
.
因此,您的 if($_ -eq $curdate)
语句将不起作用。
if($_ -eq $cur_date1)
will return 如果 $_
中包含的时间戳表示脚本开始的确切秒数 运行,则为真但是随后的 Where-Object
语句不会计算为 $true
(因为 $_
当前指的是带有日期的行,而不是错误),即使它计算了,也不会 return 任何东西(你没有将任何东西传送到 Where-Object
或指定一个 InputObject
参数参数)
作为一般规则,对于日期比较,不要使用字符串表示,使用您正在比较的日期时间对象的 Date
属性。
Wrong/frail方法:
Get-ChildItem |Where-Object { $_.LastWriteTime.ToString("ddMMyyyy") -eq $datestring }
安全方法:
$today = (Get-Date).Date
Get-ChildItem |Where-Object { $_.LastWriteTime.Date -eq $today }
如果要提取错误消息的前一个日期,最简单的方法是使用 Select-String
和 Context
参数:
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.
然后您可以使用 Select-String
的输出数据来获取和比较日期:
$Today = (Get-Date).Date
$Format = 'ddd 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")}}
当您解析 error*.txt
文件时,您可以将上次查看日期保存在变量中。所以,当你遇到Error-*
记录时,你就会知道它与什么日期有关。
$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($_,'ddd 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}
我收到了这个问题的回复,所以这是我的解决方案:
#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
这使用 [datetime] tostring()
方法来帮助创建一个正则表达式来搜索文件中的今天日期。然后它捕获从该点到文件末尾的所有内容,在换行符处将其拆分并过滤掉除错误记录之外的所有内容。
忽略获取日期的代理函数。这只是为了让脚本与测试数据一起工作。