2013-06-26 31 views
0

作为PowerShell正则表达式模式中的变量扩展方面的一个新手,在正则表达式模式下扩展变量不起作用

我想要做的是:

  • 扫描日志文件已经过两次时限
  • 对于每个日志文件之间的变化,我得到这表明它引用的日期名称的一部分。

该日期存储在变量$filedate中。 然后走线槽每一行日志文件 每当我找到一条线,看起来像:

14:00:15 blablabla

在一档名为blabla20130620.log 我想的是,数据线变得

2013-06-20 14:00:15 blablabla

应该写输出追加模式到一个文本文件(连接不同的日志文件)

这是我到现在为止(我现在在沙箱中测试,所以没有评论等...)

$Logpath = "o:\Log" 
$prevcheck="2013-06-24 19:27:14" 
$currenttd="{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) 
$batch = 1000 
[regex]$match_regex = '^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)' 
If (Test-Path "$Logpath\test.txt"){ 
Remove-Item "$Logpath\test.txt" 
} 

$files=Get-ChildItem $LogPath\*.log | Where-Object { $_.LastWriteTime -ge "$prevcheck" - and $_.LastWriteTime -le "$currenttd" -and !$_.PSIsContainer } 
foreach ($file in $files) 
{ 
$filedate=$file.Name.Substring(6,4) + "-" + $file.Name.Substring(10,2) + "-" + $file.Name.Substring(12,2) 

## This doesn't seem to work fine 
## results look like: 
## "$filedate" 14:00:15 blablabla 

$replace_regex = '"$filedate" $_' 

## I tried this too, but without success 
## The time seems to dissappear now 
## results look like: 
## 2013-06-20 blablabla 

#$replace_regex = iex('$filedate' + $_) 

(Get-Content $file.PSPath -ReadCount $batch) | 
foreach-object {if ($_ -match $match_regex) { $_ -replace $match_regex, $replace_regex}  else { $_ }}| 
out-file -Append "o:\log\test.txt" 

回答

0

你过于复杂的东西。

  • 你在你的Where-Object过滤比较日期,这样你就不会需要参考日期转换为字符串。只需使用日期:

    $prevcheck = Get-Date "2013-06-24 19:27:14" 
    $currenttd = Get-Date 
    
  • 您可以使用正则表达式来从文件名中提取日期并将其转换成所需的格式:

    $filedate = $file.BaseName -replace '^.*(\d{4})(\d{2})(\d{2})$', '$1-$2-$3' 
    
  • 您匹配时正则表达式过分正确。改为使用^(\d{2}:\d{2}:\d{2})。这是一个稍微sloppier,但它很可能就足够了,并在眼睛上更容易。

  • 要在日期前加上时间匹配,请使用"$filedate `$1"。双引号将导致$filedate被扩展到文件名的日期,转义的$(``1``)将保持分组匹配(参见Richard的解释)。

  • 虽然您可以将每个步骤的结果分配给变量,但使用单个管道会更简单。

试试这个:

$Logpath = "o:\Log" 
$Logfile = "$Logpath\test.txt" 
$prevcheck = Get-Date "2013-06-24 19:27:14" 
$currenttd = Get-Date 

If (Test-Path -LiteralPath $Logfile) { Remove-Item $Logfile } 

Get-ChildItem "$LogPath\*.log" | ? { 
    -not $_.PSIsContainer -and 
    $_.LastWriteTime -ge $prevcheck -and 
    $_.LastWriteTime -le $currenttd 
} | % { 
    $filedate = $_.BaseName -replace '^.*(\d{4})(\d{2})(\d{2})$', '$1-$2-$3' 
    Get-Content $_ | % { 
    $_ -replace '^(\d{2}:\d{2}:\d{2})', "$filedate `$1" 
    } | Out-File -Append $Logfile 
} 
+0

哇...谢谢一堆。现在我会试着更好地理解它。 – davidthijs

1

在PowerShell字符串必须用双引号(")进行变量替换。单引号(')字符串不执行变量替换。

在脚本(其中我建议你缩进代码块的内容,使结构更容易理解):

$replace_regex = '"$filedate" $_' 

其中字符串单引号,所以没有变量替换。这可以通过记住后面引号是固定的(`)字符可以被用来逃避嵌入双引号字符串双引号:

$replace_regex = "`"$filedate`" $_" 

但要记住:

  • $是一个正则表达式的元字符,所以如果你想在一个正则表达式中包含一个$双引号,它将需要被转义以避免PSH将其视为变量名的开头。
  • 变量中的任何正则表达式元字符将具有它们的正则表达式含义。考虑在替代之前转义变量的内容([regex]::Escape(string))。
+0

感谢您的解释,但遗憾的是,似乎并没有解决任何问题。它将原始行:17:02:33 ps2pdf版本2.0 28/02/2012转换为:“2013-06-22”ps2pdf版本2.0 28/02/2012当我尝试$ replace_regex ='THISISAPREFIX $ _'时,我结束随着时间的推移还有一个前缀字符串。这里是输出:THISISAPREFIX 17:02:33 ps2pdf version 2.0 28/02/2012 ps2pdf version 2.0 28/02/2012在这种情况下,我得到双线与时间在那里;不好的 – davidthijs

+0

@davidthijs:在你当前的代码中,为什么不用regex escape加concaternation来构建替换:你不需要字符串替换,因此应该更容易调试:'([regex] :: escape($ filedate)+ '$ 1')' – Richard