0

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"
  }
}
4
  • have you tried to use the JSON file as JSON? $InStuff = Get-Content -LiteralPath 'FIle.json | ConvertFrom-JSON should give you a structured object in $InStuff that you can address as you do other objects. that otta allow doing a replacement on the object directly. then you can convert from json and send it to a file. Commented Feb 15, 2019 at 10:39
  • Can you show me an example of how to do that. As I said, I am new to powershell, so I don't even know how to do a replacement on the variable and how to then save it over my existing file Commented Feb 15, 2019 at 10:43
  • i'll post this as an answer since code here is too hard to read. [grin] Commented Feb 15, 2019 at 10:56
  • $versionString -replace '^(.*)(\d\.\d\.\d)(.*)$', ('${1}' + $newversion + '${3}') Commented Feb 15, 2019 at 11:14

2 Answers 2

2

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]

Sign up to request clarification or add additional context in comments.

5 Comments

looks good. How come the formatting is all messed up when you set-content?
@r3plica - that is actually fairly normal JSON formatting. [grin] it came from the ConvertTo-JSON, not the Set-Content`.
Can it not retain the same formatting as the original file?
@r3plica In PowerShell v6 the formatting is fixed but don't expect this to be backported to earlier versions. You could help yourself with this link
@r3plica - by the time that conversion happens ... the format of the original file is long, long gone. if it is not tolerable in your situation, you will need to fix it yourself, unfortunately. i see that LotPings has pointed out a way to do that. [grin]
0

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",

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.