Reputation: 151
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?
Upvotes: 0
Views: 58
Reputation: 61068
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
Upvotes: 1