0

作为 PowerShell 编码的新手,我在 PowerShell 正则表达式模式中扩展变量时遇到了一些困难。

我想做的是:

  • 扫描在两个时间范围内更改的日志文件
  • 对于每个日志文件,我都会得到部分名称,表示它所引用的日期。

该日期存储在变量中$filedate。然后遍历每一行日志文件每当我发现一行看起来像:

14:00:15 废话

在一个名为blabla20130620.log I want the data line 的文件中

2013-06-20 14:00:15 废话

它应该以附加模式将输出写入文本文件(以连接不同的日志文件)

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

$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"
4

2 回答 2

1

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

在您的脚本中(我建议您缩进代码块的内容以使结构更易于遵循):

$replace_regex = '"$filedate" $_'

其中字符串是单引号,所以没有变量替换。这可以通过记住反引号 ( `) 字符可用于转义嵌入在双引号字符串中的双引号来解决:

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

但要记住:

  • $是一个正则表达式元字符,因此如果您想$在正则表达式中包含双引号中的 a ,则需要对其进行转义以避免 PSH 将其视为变量名的开头。
  • 变量中的任何正则表达式元字符都将具有其正则表达式含义。[regex]::Escape(string)考虑在替换 ( )之前转义变量的内容。
于 2013-06-26T07:15:48.743 回答
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})。它有点草率,但很可能就足够了,而且在眼睛上更容易。

  • 要在时间匹配之前添加日期,请使用"$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
}
于 2013-06-26T10:41:49.440 回答