none
[Powershell] Replace line in configuration file with another line RRS feed

  • Question

  • I am trying to write a flexible script that looks for lines in a configuration file that contain any one of several configuration parameters and replaces the values specified by these parameters if any are present.  I am having trouble.

    Consider that I have the configuration file below.  The full path to the file is C:\Path\File.config.

    parameter.value.omega=1.6
    parameter.value.alpha=false
    parameter.value.eplison=Windows
    parameter.value.gamma=D:\Windows\SysWOW64

    I have stored this file stored as the variable $File:

    $File = Get-Content -Path "C:\Path\File.config"


    Also consider that I have a list of parameters I want to set stored in an array $ParameterArray:

    $ParameterArray = (
     "parameter.value.alpha=true",
     "parameter.value.beta=true",
     "parameter.value.gamma=C:\Windows\System32",
    )


    So, what I want to do is loop through $ParameterArray and check $File for the presence of any of the parameters in $ParameterArray.  I'm setting the current parameter in $ParameterArray to $Parameter via a $ForEach loop.  So basically I want to look for the name of the parameter ( $Parameter.Split("=")[0] or "parameter.value.alpha" for the first example ) and if found, replace the whole line that parameter is on with the value of $Parameter.

    I have the code below, but it does not work.  The problem exists at the first part after the -replace operator.

    ForEach ($Parameter in $ParameterArray)
    {
     # This code does not work, and is where I need help.
     $File | ForEach-Object {$_ -replace "^\$Parameter\.Split\(\"=\"\)\[0\].+$",$Parameter}
    }

    Would someone mind figuring out how I can replace such a line in a text configuration file?  I am open to alternate suggestions for doing this such as using a hashtable for the parameter names and values instead of literal strings.  If there is a better way to accomplish what I am going after than heading down the path I am, please make a better suggestion.

    Thank you in advance!

    Wednesday, December 11, 2013 7:10 PM

Answers

  • Here's how I'd probably start, though "parameter.value.beta" doesn't currently exist in your sample file.  You might need additional code to keep track of which parameters were found, so you can add anything that was missing at the end of the file.

    $properties = @{
        'parameter.value.alpha' = 'true'
        'parameter.value.beta' = 'true'
        'parameter.value.gamma' = 'c:\windows\system32'
    }
    
    (Get-Content -Path .\configFile.txt) |
    ForEach-Object {
        if ($_ -match '^\s*(.*?)\s*=' -and $properties.ContainsKey($matches[1]))
        {
            "$($matches[1])=$($properties[$matches[1]])"
        }
        else
        {
            $_
        }
    } |
    Set-Content .\configFile.txt


    • Edited by David Wyatt Wednesday, December 11, 2013 7:19 PM
    • Marked as answer by Scott W. Sander Wednesday, December 11, 2013 8:13 PM
    Wednesday, December 11, 2013 7:19 PM
  • I wrote a script a while back that lets you find and replace strings in a text file using regular expressions:

    Windows IT Pro: Replacing Strings in Files Using PowerShell

    Bill

    Wednesday, December 11, 2013 7:45 PM
    Moderator
  • Here is a version that is easier to understand.  It doews not take the chance on characters that will trash Regex.

    $updates=@{
         'parameter.value.omega'='1.6'
         'parameter.value.alpha'='false'
         'parameter.value.eplison'='Windows' 
         'parameter.value.gamma'='D:\Windows\SysWOW64'
    }
    Get-Content file.config | 
         ForEach-Object{
              $key=$_.Split('=')[0]
              if($val=$updates[$key]){
                  '{0}={1}' -f $key,$val
              }else{
                  $_
              }
         }

    You can use an or as many name=value pairs as you want and it will look them up and update teh line.

    Pipe the output to a file or variable.


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, December 11, 2013 7:48 PM
    • Marked as answer by Scott W. Sander Wednesday, December 11, 2013 8:12 PM
    Wednesday, December 11, 2013 7:48 PM

All replies

  • Most app.config files are XML files.  XML commands can target edit any value very easily.  Using string methods can be very hard.

    Post a copy of the XML.


    ¯\_(ツ)_/¯

    Wednesday, December 11, 2013 7:16 PM
  • Here's how I'd probably start, though "parameter.value.beta" doesn't currently exist in your sample file.  You might need additional code to keep track of which parameters were found, so you can add anything that was missing at the end of the file.

    $properties = @{
        'parameter.value.alpha' = 'true'
        'parameter.value.beta' = 'true'
        'parameter.value.gamma' = 'c:\windows\system32'
    }
    
    (Get-Content -Path .\configFile.txt) |
    ForEach-Object {
        if ($_ -match '^\s*(.*?)\s*=' -and $properties.ContainsKey($matches[1]))
        {
            "$($matches[1])=$($properties[$matches[1]])"
        }
        else
        {
            $_
        }
    } |
    Set-Content .\configFile.txt


    • Edited by David Wyatt Wednesday, December 11, 2013 7:19 PM
    • Marked as answer by Scott W. Sander Wednesday, December 11, 2013 8:13 PM
    Wednesday, December 11, 2013 7:19 PM
  • That might work if it is some kind of a weird text file.  It will not likely work if it is XML.

    Loading as XML the values can just be directly assigned.  That is the point of using XML as XML.  Text methods run the risk of damaging the XML.


    ¯\_(ツ)_/¯

    Wednesday, December 11, 2013 7:23 PM
  • I'm not sure where you're getting XML from the OP, other than possibly a file with a .config extension.  Nothing in his sample format or code looks like XML.
    Wednesday, December 11, 2013 7:25 PM
  • The dummy example looks like an APP.config file:
      The full path to the file is C:\Path\File.config

    The strings are standard PowerShell XML strings

    parameter.value.alpha='somevalue'

    <parameter>
          <value>
               <alpha>orgvalue</alpha>
               <beta>orgvalue</beta>
               <gamma>orgvalue</gamma>
          </value>

    </parameter>

    Of course I could be wrong but I have seen this before.

    The parameter names are all dummies for demo but the structure is normal to an app.config file.  Although some things may be lost in the example posted.

    If it is somehow a plain line by line text file then there is a very easy way to do it.  We need an example of the file to know.


    ¯\_(ツ)_/¯




    • Edited by jrv Wednesday, December 11, 2013 7:34 PM
    Wednesday, December 11, 2013 7:31 PM
  • Most app.config files are XML files.  XML commands can target edit any value very easily.  Using string methods can be very hard.

    Post a copy of the XML.


    ¯\_(ツ)_/¯


    I'm working with a text file, not XML.  Each parameter is on its own line with the parameter name preceding an equal sign (=) and the parameter value or switch after the equal sign.  There is no markup or anything like what you would see in an XML file.  It basically looks almost exactly like my example except that I'm using generic parameter names and false values that are meant to illustrate what the file literally looks like.
    Wednesday, December 11, 2013 7:32 PM
  • Most app.config files are XML files.  XML commands can target edit any value very easily.  Using string methods can be very hard.

    Post a copy of the XML.


    ¯\_(ツ)_/¯


    I'm working with a text file, not XML.  Each parameter is on its own line with the parameter name preceding an equal sign (=) and the parameter value or switch after the equal sign.  There is no markup or anything like what you would see in an XML file.  It basically looks almost exactly like my example except that I'm using generic parameter names and false values that are meant to illustrate what the file literally looks like.

    So you are saying that the lines in teh file look like this:

    parameter.value.omega=1.6

    That being a whole line.


    ¯\_(ツ)_/¯

    Wednesday, December 11, 2013 7:35 PM
  • It's a Java JRE deployment.properties file.  Here is an example from my computer:

    #deployment.properties
    #Wed Dec 11 11:05:20 EST 2013
    deployment.modified.timestamp=1382623794404
    deployment.javaws.appicon.index=C\:\\Users\\scottwsx96\\AppData\\LocalLow\\Sun\\Java\\Deployment\\cache\\6.0\\appIcon\\appIcon.xml
    deployment.javaws.splash.index=C\:\\Users\\scottwsx96\\AppData\\LocalLow\\Sun\\Java\\Deployment\\cache\\6.0\\splash\\splash.xml
    deployment.version=7.21
    deployment.security.validation.crl=true
    deployment.browser.path=C\:\\Program Files\\Internet Explorer\\iexplore.exe
    #Java Deployment jre's
    #Wed Dec 11 11:05:20 EST 2013
    deployment.javaws.jre.0.registered=true
    deployment.javaws.jre.0.platform=1.6
    deployment.javaws.jre.0.osname=Windows
    deployment.javaws.jre.0.path=C\:\\Program Files (x86)\\Java\\jre6\\bin\\javaw.exe
    deployment.javaws.jre.0.product=1.6.0_45
    deployment.javaws.jre.0.osarch=x86
    deployment.javaws.jre.0.location=http\://java.sun.com/products/autodl/j2se
    deployment.javaws.jre.0.enabled=true
    deployment.javaws.jre.0.args=
    

    Frankly, right now the only property I want to enforce is "deployment.security.validation.crl=true", but I want to write a script that is flexible enough so that any parameter could be enforced.

    And yes, David Wyatt, I plan on adding code that will add the parameter if it is not present.  That is easy (Add-Content).  I'm just having trouble changing existing parameters.

    Wednesday, December 11, 2013 7:41 PM
  • Something like this:

    $updates=@{
         'parameter.value.omega'='1.6'
         'parameter.value.alpha'='false'
         'parameter.value.eplison'='Windows' 
         'parameter.value.gamma'='D:\Windows\SysWOW64'
    }
    cat file.config | %{ if($x=$updates[$_.Split('=')[0]]){$updates[$_.Split('=')[0]]+'='+$x}else{$_}

    It is more exacting then RegEx but Regex can do it to.


    ¯\_(ツ)_/¯

    Wednesday, December 11, 2013 7:43 PM
  • I wrote a script a while back that lets you find and replace strings in a text file using regular expressions:

    Windows IT Pro: Replacing Strings in Files Using PowerShell

    Bill

    Wednesday, December 11, 2013 7:45 PM
    Moderator
  • Here is a version that is easier to understand.  It doews not take the chance on characters that will trash Regex.

    $updates=@{
         'parameter.value.omega'='1.6'
         'parameter.value.alpha'='false'
         'parameter.value.eplison'='Windows' 
         'parameter.value.gamma'='D:\Windows\SysWOW64'
    }
    Get-Content file.config | 
         ForEach-Object{
              $key=$_.Split('=')[0]
              if($val=$updates[$key]){
                  '{0}={1}' -f $key,$val
              }else{
                  $_
              }
         }

    You can use an or as many name=value pairs as you want and it will look them up and update teh line.

    Pipe the output to a file or variable.


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, December 11, 2013 7:48 PM
    • Marked as answer by Scott W. Sander Wednesday, December 11, 2013 8:12 PM
    Wednesday, December 11, 2013 7:48 PM
  • There is a config tool for vre config files.  It is somewhere on the Oracle Java Developer site.  It takes name/value pairs and updates the config file.


    ¯\_(ツ)_/¯

    Wednesday, December 11, 2013 7:50 PM
  • Thank you for your help, everyone!  Everyone's answers led me to a valid solution.
    Wednesday, December 11, 2013 8:12 PM