0

As a novice in powershell coding, I have some difficulties with expansion of a variable in PowerShell regex patterns.

What I wanted to do is:

  • Scan for logfiles that have been changed between two timeframes
  • For each of the logfiles, I get part of the name which indicates the date it is referencing to.

That date is stored in the variable $filedate. Then go trough each line logfiles Whenever I find a line that looks like:

14:00:15 blablabla

In a file named blabla20130620.log I want that the data line becomes

2013-06-20 14:00:15 blablabla

It should write the output in append mode to a text file (to concatenate different log files)

Here is what I got until now (I'm testing in a sandbox now, so no comments etc...)

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

2 Answers 2

1

You're over-complicating things.

  • You're comparing dates in your Where-Object filter, so you don't need to transform your reference dates to strings. Just use dates:

    $prevcheck = Get-Date "2013-06-24 19:27:14"
    $currenttd = Get-Date
    
  • You can use a regular expression to extract the date from the file name and transform it into the desired format:

    $filedate = $file.BaseName -replace '^.*(\d{4})(\d{2})(\d{2})$', '$1-$2-$3'
    
  • Your regular expression for matching the time is overly correct. Use ^(\d{2}:\d{2}:\d{2}) instead. It's a little sloppier, but it will most likely suffice and is a lot easier on the eye.

  • To prepend the time-match with the date, use "$filedate `$1". The double quotes will cause $filedate to be expanded to the date from the file name, and the escaped $ (``$1`) will keep the grouped match (see Richard's explanation).

  • While you can assign the results from each step to variables, it'd be simpler to just use a single pipeline.

Try this:

$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
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow... thanks a bunch. Now I'll try to understand it a little better.
1

In PowerShell strings have to be in double quotes (") for variable substitution. Single quoted (') strings do not perform variable substitution.

In your script (in which I suggest you indent the content of code blocks to make the structure easier to follow):

$replace_regex = '"$filedate" $_'

where the string is single quoted, so no variable substitution. This can be fixed by remembering the back-quote (`) character can be used to escape double quotes embedded in a double quoted string:

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

But remember:

  • $ is a regex meta-character, so if you want to include a $ in a regex in double quotes it will need to be escaped to avoid PSH treating it as the start of the variable name.
  • Any regex meta-characters in the variable will have their regex meaning. Consider escaping the content of the variable before substitution ([regex]::Escape(string)).

2 Comments

Thanks for the explanation but unfortunately that doesn't seem to solve anything. It converts the original line: 17:02:33 ps2pdf version 2.0 28/02/2012 into: "2013-06-22" ps2pdf version 2.0 28/02/2012 When I try $replace_regex = 'THISISAPREFIX $_' , I end up with the time still in place and a prefixed string. Here is the output: THISISAPREFIX 17:02:33 ps2pdf version 2.0 28/02/2012 ps2pdf version 2.0 28/02/2012 In that case I get double lines with the time in there ; not good either
@davidthijs: In your current code why not build the replacement with regex escape plus concaternation: you don't need string substitution and thus should be easier to debug: ([regex]::escape($filedate) + '$1')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.