I have just recently started working with PowerShell scripts and I am currently working with a .ini file that is being modified by another program as well, which is why I'm looking for a dynamic approach. I have also tried to test it with a .txt file to see if it has another result.
The file I'm looking to edit is organized like so:
[topic1]
Value1=1
Value2=3
Value3=keep
[topic2]
Value1=2
Value2=4
(... etc.)
There are several topics which have different amounts of values, however, topic 1 will always have 3 values and topic 2 will always have 2 values, so we would know the number of lines and name of value I'll have to replace using powershell depending on the topic.
Now I want to change the values for topic2 like so:
$file = 'D:\sample.ini'
$find = 'Value1=2'
$replace = 'Value1=3'
(Get-Content $file).replace($find, $replace) | Set-Content $file
expecting the .ini file to look like this:
[topic1]
Value1=1
Value2=3
Value3=keep
[topic2]
Value1=3
Value2=4
(... etc.)
#1 I do not know how to only focus on the 2 lines after "[topic2]". (In case that value1 for both topic1 and topic2 are the same name and value)
#2 The code I am using is not changing anything at all and PowerShell does not give me an error, it only immediately closes. I have tried to use different approaches to replace something, but either the .txt file was empty after the process or nothing happened at all.
#3 It would also be neat to be able to replace several lines at once, if possible, but I could also do it subsequently. (e.g. value1=2,value2=4->value1=3,value2=2)
-
2This is not an answer but more of an advice. Your objective seems quite common: manipulate an ini using PS. In cases like that and speaking only for myself I tend to take a step back and think to myself 'why re-invent the wheel, hasn't somebody already solved this?' And sure enough, when you browse the PowerShell Gallery, there are some packages there that can manipulate ini files. No idea if they are of use to you, but they may save you time. Not as much fun as solving the puzzle by yourself (that is obviously a subjective stand), but probably quicker.Rno– Rno2020年09月26日 22:36:10 +00:00Commented Sep 26, 2020 at 22:36
-
Thank you for your general advice! I was not aware and this will definitely help me. Concerning this one thing, I'm working on a game which accesses this file and reads the information. I want to automatically change this information with the help of task scheduler and ps script, therefore, in this case I need this very specific thing to work.Joey R– Joey R2020年09月28日 15:49:51 +00:00Commented Sep 28, 2020 at 15:49
1 Answer 1
As Arno van Boven commented, there are tools that exist to work with ini files already. However, if you want to use regex and replace them, see this example.
$tempfile = New-TemporaryFile
@'
[topic1]
Value1=1
Value2=3
Value3=keep
[topic2]
Value1=2
Value2=4
(... etc.)
'@ | Set-Content $tempfile -Encoding UTF8
(get-content $tempfile -raw) -replace '(?s)(?<=\[topic2\].+=)\d+','3' -replace '(?s)(?<=\[topic2\].+=.+=)\d+','5'
Regex breakdown
(?s) treats the entire text as one string, . will match new lines as well. This requires the -Raw flag on Get-Content
(?<=...) Positive lookbehind, the "match" must follow this pattern
\[..\] The slashes are simply escaping the square brackets, otherwise regex would treat it as a character group
topic2 this is a literal match for that word
.+= The .+ will consume all the characters including new lines up until the literal = which is the last character before the value we are after.
\d+ Match 0 or more numerical characters. This is the value we are looking to replace
For the second value, we simply add one more set of .+= to skip over the first value.
The output is
[topic1]
Value1=1
Value2=3
Value3=keep
[topic2]
Value1=3
Value2=5
(... etc.)
Simply pipe it back to write it to the file.
(get-content $tempfile -raw) -replace '(?s)(?<=\[topic2\].+=)\d+(?=\r?\n)','3' -replace '(?s)(?<=\[topic2\].+=.+=)\d+(?=\r?\n)','5' | Set-Content $tempfile -Encoding UTF8