0

I have the following txt file.

[AppRemover]
Enable=0

[CleanWipe]
Enable=0

[RerunSetup]
Enable=0

How do I change the Enable=0 to Enable=1 under [CleanWipe] only?

Below is how I plan on using the code with my file.

$Path = C:\temp\file.txt
$File = Get-Content -Path $Path
# Code to update file
$File | Out-File $Path
Keith
  • 689
  • 10
  • 27
  • As an aside: Consider using a dedicated INI file parser, such as the popular third-party INI file-parsing module [PSIni](https://www.powershellgallery.com/packages/PsIni/2.0.3), whose use is demonstrated in [this answer](https://stackoverflow.com/a/55341293/45375). – mklement0 Sep 24 '19 at 15:35

1 Answers1

1

You can use -replace to update the value if it is 0.

$Path = C:\temp\file.txt
(Get-Content $Path -Raw) -replace "(?<text>\[CleanWipe\]\r?\nEnable=)0",'${text}1' |
    Set-Content $Path

Using a module that parses INI files will be the best solution though. I'd recommend trying PsIni.

Explanation:

The -Raw switch reads the file contents as a single string. This makes it easier to work with newline characters.

-replace performs a regex match and then replace. Below is the regex match breakdown.

  • (?<text>) is a named capture group. Anything matched within that capture group can be recalled in the replace string as '${text}'.
  • \[CleanWipe\] is a literal match of [CleanWipe] while escaping the [] characters with \.
  • \r? is optional carriage return
  • \n is the newline character
  • Enable= is a literal match
  • 0 is a literal match

The replace string is the capture group contents and 1 when a match exists. Technically, a capture group is not needed if you want to use a positive lookbehind instead. The positive lookbehind assertion is (?<=). That solution would look like the following:

$Path = C:\temp\file.txt
(Get-Content $Path -Raw) -replace "(?<=\[CleanWipe\]\r?\nEnable=)0",'1' |
    Set-Content $Path

The problem with the -replace solutions as they written is they will update the file regardless of a change actually being made to the contents. You would need to add an extra comparison to prevent that. Other issues could be extra white space on any of these lines. You can account for that by adding \s* where you think those possibilities may exist.


Alternative With More Steps:

$file = Get-Content $Path
$TargetIndex = $file.IndexOf('[CleanWipe]') + 1
if ($file[$TargetIndex] -match 'Enable=0') {
    $file[$TargetIndex] = 'Enable=1'
    $file | Set-Content $Path
}

This solution will only update the file if it meets the match condition. It uses the array method IndexOf() to determine where [CleanWipe] is. Then assumes the line you want to change is in the next index.

IndexOf() is not the only way to find an index. The method requires that your line match the string exactly. You can use Select-String (case-insensitive by default) to return a line number. Since it will be a line number and not an index (indexes start at 0 while line numbers start at 1), it will invariably be the index number you want.

$file = Get-Content $Path
$TargetIndex = ($file | Select-String -Pattern '[CleanWipe]' -SimpleMatch).LineNumber
if ($file[$TargetIndex] -match 'Enable=0') {
    $file[$TargetIndex] = 'Enable=1'
    $file | Set-Content $Path
}
AdminOfThings
  • 23,946
  • 4
  • 17
  • 27