r3plica
r3plica

Reputation: 13397

PowerShell replace value in file

I am really new to powershell. I need to replace a value (that is always changing) in a file. The value looks like this:

"version": "2.4.5",

And I wish to replace the number. I have this bit of code:

(Get-Content .\bower.json).replace('2.4.5', $version) | Set-Content .\bower.json

But that requires that the version number is always 2.4.5 before setting it to the new version. As you can figure out, the next time around that number won't be the same.

Does anyone know of a way I can replace the version number regardless of what it is? Maybe with regex?


After a bit of playing, I have tried this:

$pattern = '\"version\": \"(.*)\"'
$replace = """version"": ""$version""";
(Get-Content .\bower.json).replace($pattern, $replace) | Set-Content .\bower.json

But it doesn't replace anything :( If I run:

$replace -match $pattern

it returns "True", so I would expect it to replace correctly? This is my bower.json file:

{
  "name": "sapphire",
  "version": "2.4.5",
  "dependencies": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-barcode": "0.0.4",
    "angular-bootstrap": "2.5.0",
    "angular-cookies": "~1.7.4",
    "angular-google-maps": "2.4.1",
    "angular-loading-bar": "0.9.0",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-simple-cache": "1.0.6",
    "angular-touch": "~1.7.4",
    "angular-ui-mask": "1.8.7",
    "angular-ui-select": "0.19.8",
    "bootstrap-sass-official": "3.3.7",
    "ng-idle": "1.3.2",
    "ng-notify": "0.8.0",
    "vkbeautify": "*",
    "ngclipboard": "~2.0.0",
    "angular-confirm": "angular1-confirm#1.1.0",
    "angular-ui-router": "~1.0.20",
    "font-awesome": "^5.6.1",
    "ng-confirm": "angular-confirm#^1.1.0"
  },
  "devDependencies": {},
  "appPath": "src",
  "moduleName": "sapphire",
  "overrides": {
    "bootstrap": {
      "main": [
        "less/bootstrap.less",
        "dist/css/bootstrap.css",
        "dist/js/bootstrap.js"
      ]
    }
  },
  "resolutions": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-cookies": "~1.7.4",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-touch": "~1.7.4",
    "components-font-awesome": "~5.0.6",
    "ngclipboard": "~2.0.0",
    "clipboard": "^2.0.0",
    "angular-ui-router": "~1.0.20"
  }
}

Upvotes: 0

Views: 889

Answers (2)

pesh
pesh

Reputation: 45

To answer on your regex approach:

The Replace() method on the string itself is used for simple replacements. PowerShell cannot use regex there.

One way to be done is to use the -replace operator which can make advanced replacements using regex.

Here is an example:

$data = @'
{
  "name": "sapphire",
  "version": "2.4.5",
  "dependencies": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-barcode": "0.0.4",
    "angular-bootstrap": "2.5.0",
    "angular-cookies": "~1.7.4",
    "angular-google-maps": "2.4.1",
    "angular-loading-bar": "0.9.0",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-simple-cache": "1.0.6",
    "angular-touch": "~1.7.4",
    "angular-ui-mask": "1.8.7",
    "angular-ui-select": "0.19.8",
    "bootstrap-sass-official": "3.3.7",
    "ng-idle": "1.3.2",
    "ng-notify": "0.8.0",
    "vkbeautify": "*",
    "ngclipboard": "~2.0.0",
    "angular-confirm": "angular1-confirm#1.1.0",
    "angular-ui-router": "~1.0.20",
    "font-awesome": "^5.6.1",
    "ng-confirm": "angular-confirm#^1.1.0"
  },
  "devDependencies": {},
  "appPath": "src",
  "moduleName": "sapphire",
  "overrides": {
    "bootstrap": {
      "main": [
        "less/bootstrap.less",
        "dist/css/bootstrap.css",
        "dist/js/bootstrap.js"
      ]
    }
  },
  "resolutions": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-cookies": "~1.7.4",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-touch": "~1.7.4",
    "components-font-awesome": "~5.0.6",
    "ngclipboard": "~2.0.0",
    "clipboard": "^2.0.0",
    "angular-ui-router": "~1.0.20"
  }
}
'@

$rex = '(?<="version": ")(.*)(?=",)'

$data -replace $rex, "5.1" 

The regular expression is getting anything between "version": " and ",. Thus the replace operator will change all values matched by this pattern with 5.1. You should get this as a result:

"version": "5.1",

Upvotes: 0

Lee_Dailey
Lee_Dailey

Reputation: 7489

since you have a valid JSON file, the better approach seems to be to use it as such. [grin] this code does the following ...

  • fakes reading in the JSON file
    i didn't feel like creating a test file for this.
  • converts that to a PSCustomObject with ConvertFrom-JSON
  • shows the imported .Version property value
  • changes that value
  • shows the now-current value of the .Version prop
  • converts the object back to JSON and writes it to a file

here's the code ...

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = @'
{
  "name": "sapphire",
  "version": "2.4.5",
  "dependencies": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-barcode": "0.0.4",
    "angular-bootstrap": "2.5.0",
    "angular-cookies": "~1.7.4",
    "angular-google-maps": "2.4.1",
    "angular-loading-bar": "0.9.0",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-simple-cache": "1.0.6",
    "angular-touch": "~1.7.4",
    "angular-ui-mask": "1.8.7",
    "angular-ui-select": "0.19.8",
    "bootstrap-sass-official": "3.3.7",
    "ng-idle": "1.3.2",
    "ng-notify": "0.8.0",
    "vkbeautify": "*",
    "ngclipboard": "~2.0.0",
    "angular-confirm": "angular1-confirm#1.1.0",
    "angular-ui-router": "~1.0.20",
    "font-awesome": "^5.6.1",
    "ng-confirm": "angular-confirm#^1.1.0"
  },
  "devDependencies": {},
  "appPath": "src",
  "moduleName": "sapphire",
  "overrides": {
    "bootstrap": {
      "main": [
        "less/bootstrap.less",
        "dist/css/bootstrap.css",
        "dist/js/bootstrap.js"
      ]
    }
  },
  "resolutions": {
    "angular": "~1.7.4",
    "angular-animate": "~1.7.4",
    "angular-cookies": "~1.7.4",
    "angular-mocks": "~1.7.4",
    "angular-resource": "~1.7.4",
    "angular-sanitize": "~1.7.4",
    "angular-touch": "~1.7.4",
    "components-font-awesome": "~5.0.6",
    "ngclipboard": "~2.0.0",
    "clipboard": "^2.0.0",
    "angular-ui-router": "~1.0.20"
  }
}
'@

$NewVersion = '6.6.6'

$FromJSON = $InStuff |
    ConvertFrom-Json

# show the current imported value
$FromJSON.Version

$FromJSON.Version = $NewVersion

# show the new value
$FromJSON.Version

# send it to a file    
$FromJSON |
    ConvertTo-Json |
    Set-Content -LiteralPath "$env:TEMP\r3plica_-_NewVersion.json"

on screen output ...

2.4.5
6.6.6

content of the new file ...

{
    "name":  "sapphire",
    "version":  "6.6.6",
    "dependencies":  {
                         "angular":  "~1.7.4",
                         "angular-animate":  "~1.7.4",
                         "angular-barcode":  "0.0.4",
                         "angular-bootstrap":  "2.5.0",
                         "angular-cookies":  "~1.7.4",
                         "angular-google-maps":  "2.4.1",
                         "angular-loading-bar":  "0.9.0",
                         "angular-mocks":  "~1.7.4",
                         "angular-resource":  "~1.7.4",
                         "angular-sanitize":  "~1.7.4",
                         "angular-simple-cache":  "1.0.6",
                         "angular-touch":  "~1.7.4",
                         "angular-ui-mask":  "1.8.7",
                         "angular-ui-select":  "0.19.8",
                         "bootstrap-sass-official":  "3.3.7",
                         "ng-idle":  "1.3.2",
                         "ng-notify":  "0.8.0",
                         "vkbeautify":  "*",
                         "ngclipboard":  "~2.0.0",
                         "angular-confirm":  "angular1-confirm#1.1.0",
                         "angular-ui-router":  "~1.0.20",
                         "font-awesome":  "^5.6.1",
                         "ng-confirm":  "angular-confirm#^1.1.0"
                     },
    "devDependencies":  {

                        },
    "appPath":  "src",
    "moduleName":  "sapphire",
    "overrides":  {
                      "bootstrap":  {
                                        "main":  "less/bootstrap.less dist/css/bootstrap.css dist/js/bootstrap.js"
                                    }
                  },
    "resolutions":  {
                        "angular":  "~1.7.4",
                        "angular-animate":  "~1.7.4",
                        "angular-cookies":  "~1.7.4",
                        "angular-mocks":  "~1.7.4",
                        "angular-resource":  "~1.7.4",
                        "angular-sanitize":  "~1.7.4",
                        "angular-touch":  "~1.7.4",
                        "components-font-awesome":  "~5.0.6",
                        "ngclipboard":  "~2.0.0",
                        "clipboard":  "^2.0.0",
                        "angular-ui-router":  "~1.0.20"
                    }
}

note the new value of version ... [grin]

Upvotes: 2

Related Questions