0

I have to update a file with one line every day in three different sections of the line.

The line in the file on January 15th before the update was as follows:

XXXXXX 01130113352021013115126XXXX 2005000113 XXX XXX XXX I

So, the line is divided by spaces into 7 segments. I have to update the first 4 characters of the second segment with MMDD<-1>, the 13 characters prior to the XXXX in the second segment with YYYYJJJHHMMSS<-1> and then the last four digits of the third segment with MMDD<-1>

Here is my code:

#get the year minuse 1 day, get the day of the year minuse 1 day, get the current time 
$yeardayofyeartime = (get-date).AddDays(-1).ToString("yyyy") + (get-date).AddDays(-1).dayofyear.ToString("000") + (get-date).ToString("HHmmss")
Add-Content -Path $logpath -Value "The year, Julian date, and time is:"
Add-Content -Path $logpath -Value $yeardayofyeartime

#get the current month and day minus 1
$monthday = (get-date).AddDays(-1).ToString("MMdd")
Add-Content -Path $logpath -Value "The month and the day is: $monthday."
Add-Content -Path $logpath -Value $monthday

$Content = Get-Content $source
Add-Content -Path $logpath -Value "Content in the file before update is:"
Add-Content -Path $logpath -Value $Content

$Content.Replace($Content.Substring(12, 4), $monthday).Replace($Content.Substring(22, 13), $yeardayofyeartime).Replace($Content.Substring(51, 4), $monthday) | Out-File -encoding ASCII $source

Add-Content -Path $logpath -Value "Content in the file after update:"
Get-Content $source | Add-Content -Path $logpath

Add-Content -Path $logpath -Value "*********************************************************************************************************"
    
exit 0

The odd thing is that it's also updating 16,4 with MMDD<-1> and I don't know why. Here's what I've created a log to monitor these changes and here's what I found. These logs start on the 15th.

The year, Julian date, and time is: 2021014060002 The month and the day is: 0114. 0114 Content in the file before update is: XXXXXX 01130113352021013115126XXXX 2005000113 XXX XXX XXX I
Content in the after update: XXXXXX 01140114352021014060002XXXX 2005000114 XXX XXX XXX I


The year, Julian date, and time is: 2021015060002 The month and the day is: 0115. 0115 Content in the file before update is: XXXXXX 01140114352021014060002XXXX 2005000114 XXX XXX XXX I
Content in the after update: XXXXXX 01150115352021015060002XXXX 2005000115 XXX XXX XXX I


The year, Julian date, and time is: 2021016060002 The month and the day is: 0116. 0116 Content in the file before update is: XXXXXX 01150115352021015060002XXXX 2005000115 XXX XXX XXX I
Content in the after update: XXXXXX 01160116352021016060002XXXX 2005000116 XXX XXX XXX I


The year, Julian date, and time is: 2021017060002 The month and the day is: 0117. 0117 Content in the file before update is: XXXXXX 01160116352021016060002XXXX 2005000116 XXX XXX XXX I
Content in the after update: XXXXXX 01170117352021017060002XXXX 2005000117 XXX XXX XXX I


The year, Julian date, and time is: 2021018060002 The month and the day is: 0118. 0118 Content in the file before update is: XXXXXX 01170117352021017060002XXXX 2005000117 XXX XXX XXX I
Content in the after update: XXXXXX 01180118352021018060002XXXX 2005000118 XXX XXX XXX I


The year, Julian date, and time is: 2021019060002 The month and the day is: 0119. 0119 Content in the file before update is: XXXXXX 01180118352021018060002XXXX 2005000118 XXX XXX XXX I
Content in the after update: XXXXXX 01190119352021019060002XXXX 2005000119 XXX XXX XXX I


The year, Julian date, and time is: 2021020060002 The month and the day is: 0120. 0120 Content in the file before update is: XXXXXX 01190119352021019060002XXXX 2005000119 XXX XXX XXX I
Content in the after update: XXXXXX 01200120352021020060002XXXX 2005000120 XXX XXX XXX I


Any ideas why this part is updating as well?

0

1 Answer 1

1

I wouldn't use the repeated .Replace() methods here, but rather split the string into segments and do the replacements on each segment. Then rejoin these to form the new content:

$segments = $content -split ' '
# split the second segment into 4 parts
$subs = $segments[1] -split '^(\d{4})(\d{6})(\d{13})(.*)' -ne ''
$subs[0] = $monthday
$subs[2] = $yeardayofyeartime
# rejoin the sub parts to form the new $segment[1]
$segments[1] = $subs -join ''

# replace the third segment
# or use $segments[2] = $segments[2] -replace '(.*)\d{4}$', "`$1$monthday"
$segments[2] = $segments[2].Substring(0,6) + $monthday

# rejoin the updated segments to form the new content line
$content = $segments -join ' '

To explain what @g.sulman asked in his comment: "What does -ne '' do on the $subs = ... line"

PowerShell's -split operator has a gotcha:

When the input string to splits starts (and in this case also ends) in a regex match, -split treats the first and last element of the split to be an empty string.

Demo:

$subs = '01130113352021013115126XXXX' -split '^(\d{4})(\d{6})(\d{13})(.*)'
for ($i = 0; $i -lt $subs.Count; $i++) {
    '{0}: {1}' -f $i, $subs[$i]
}

Result:

0: 
1: 0113
2: 011335
3: 2021013115126
4: XXXX
5:

By passing the resulting array to -ne '', we filter out these empty strings:

$subs = '01130113352021013115126XXXX' -split '^(\d{4})(\d{6})(\d{13})(.*)' -ne ''
for ($i = 0; $i -lt $subs.Count; $i++) {
    '{0}: {1}' -f $i, $subs[$i]
}

Result:

0: 0113
1: 011335
2: 2021013115126
3: XXXX
Sign up to request clarification or add additional context in comments.

2 Comments

What does -ne ' on the $subs = .. line do?
@g.sulman That is needed to ensure the array returned by -split does not contain empty elements. Please see my edit where I explain.

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.