I have a configuration.txt file which my script uses to populate variables in my script. The Tex file reads like:
Setting1= Yes
Setting2= Yes
Setting3= Yes
I then populate my variables as such (to pull just Yes or No):
$Setting1=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting1='})
$Setting1=($Setting1 -Split '=', 2)[1].trim()
$Setting2=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting2='})
$Setting2=($Setting2 -Split '=', 2)[1].trim()
$Setting3=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting3='})
$Setting3=($Setting3 -Split '=', 2)[1].trim()
Then I have some logic and if the user, via prompts in my script, change these settings, the script updates the text file with the following code:
((Get-Content -Path .\configuration.txt -Raw | Where-Object {$_ -match 'Setting1'}) -replace $Setting1, $UserSetting1) | Set-Content -Path .\configuration.txt
Where $UserSetting1 is the user's input (either 'yes' or 'no').
Now what this is doing is changing every 'yes' or 'no' in the configuration file instead of only changing the 'yes' or 'no' on the particular line I am trying to use the match function to pull out.
In other words if the user wants to change setting1 to 'no' and keep settings 2 & 3 as a 'yes'; the script is changing all the settings to Yes, instead of only setting1.
I am under the impression that I have to use -Raw in order to perform a -replace, but as stated above, it seems that the -match function doesn't work with the -Raw function...and if I don't use -raw, then my configuration file is re-written with only the single line that I matched.
You could just use the Replace Operator to make an update.
$UserSetting1 = 'No'
(Get-Content -Path .\configuration.txt) -replace '(?<=Setting1=).*',$UserSetting1 |
Set-Content
Since -replace
uses a regex matching mechanism, you can construct the match to only return the data you want to replace. The replacement string can be a variable. See below for the regex explanation. It matches the remaining characters on a line after Setting1=
and then replaces those characters with the value stored in $UserSetting1
. Lines that have no match will be returned as is without replacement.
(?<=)
is the regex positive lookbehind assertion. It asserts that at a given position in the string that there is an exact match behind it.Setting1=
literal match of the string Setting1=
..*
as many characters as possible until the end of string (just before the newline character)[1].Using the -Raw
switch reads the file contents as a single string. If you perform a regex match (-match
) on a single string that has a match, $true
is returned. The entire string is considered a match and defaults to capture group 0. $matches[0]
contains that match. Therefore, if you use -replace
to replace a substring within that match, it will replace every instance of that substring that meets the -replace
matching criteria.
If the -Raw
switch is not used, then the file contents are read in as an array of lines. -replace
alone would still replace every instance of a match. However, you can now use -match
and Where-Object
to execute different code for certain matched lines.
Combining -match
and -replace
without -Raw
could lead to only a subset of your read data. As you process each line of the file, -match
will essentially filter out any lines that don't return $true
before you process any replacements. This scenario is fine for returning the replacement, but can cause issues when you are trying to rewrite an entire file. You would need additional logic to track which array elements you have and have not modified and output them appropriately when you update your content.
[1] .
can match newline characters if the regex mode is single-line. You can enable this mode in the -replace
regex by beginning it with (?s)
.