How to use a variable in powershell replace command (from Windows CMD) - powershell

I'm currently using the following command to do a find and replace in a file (I googled the code and just added the -encoding UTF8 because otherwise Apache refused to read the file as a php file):
powershell -Command "(gc app.php) -replace '/../', '/../new_project_name/' | Out-File -encoding UTF8 app.php"
The code is working as long as the folder is "new_project_name". new_project_name should actually be a variable name though. E.g. if SET new_project_name=example then the powershell would be as follows:
powershell -Command "(gc app.php) -replace '/../', '/../example/' | Out-File -encoding UTF8 app.php"
I've tried passing a variable to the powershell command but either get errors or no changes are made.

Variables defined in your batch script are available in the env: scope in PowerShell commands started from the batch script (as it inherits the parent script's environment):
Set "new_name=example"
powershell -Command "(gc app.php) -replace '/../', \"/../$env:new_name/\" | ..."
Note that if you use the variable inside a (PowerShell) string you must put that string in double quotes. Single quotes will not work. Escape the nested double quotes with backslashes for CMD.

Related

Escape double quotes and single quotes in Jenkins pipeline script

I have one powershell command inside that both Double quotes and single quotes are present and it's needed for sure in order to make the command execute successfully in dos prompt. I am not sure how to make it escape in pipeline script.
bat "powershell -Command "(Get-Content "${Physical_FolderLoc}\\${Stord_Process_Name}.txt") | ForEach-Object { $_ -replace [RegEx]::Escape('E:\\config'), 'I:\\config' } | Set-Content "${Physical_FolderLoc}\\${Stord_Process_Name}.txt" " "
In the above command you can see the second last " is ending quote for Get Content and last one is for bat command.
I tried the above command with triple slash but getting groovy error.
groovy.lang.MissingPropertyException: No such property: _ for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty
Please help me to resolve this.
Change each internal double quoted string, eg:
"${Physical_FolderLoc}\\${Stord_Process_Name}.txt"
to:
('{0}\\{1}.txt' -f $Physical_FolderLoc, $Stord_Process_Name)
I got the exact issue why the command was not escaping. There is a stand alone $ symbol in the powershell command which is also a system character for groovy, so that need to be escaped as well.(The $ character which is after ForEach-Object {). It's now prefixed with \, so escaped.
Now the complete command is :
bat "powershell -Command \"(Get-Content ${Physical_FolderLoc}\\${Stord_Process_Name}.txt) | ForEach-Object { \$_ -replace [RegEx]::Escape('E:\\config'), 'I:\\config' } | Set-Content ${Physical_FolderLoc}\\${Stord_Process_Name}.txt\" "
Though no one had tried to help much, but still thanks a lot for the suggestion.

Multiline powershell function inside batch script

I want to run .bat-script which calls some powershell function inside it. Function is not so small, so I want to split it. But I cannot do it, escape symbols doesn`t help ( ` ,^).
Script example:
set file=%1
set function="$file=$Env:file; ^
$hash = CertUtil -hashfile $file SHA256 | Select -Index 1"
powershell -command %function%
You can leave the quote at the end of each line like so:
set file=%1
set function="$file=$Env:file; "^
"$hash = CertUtil -hashfile $file SHA256 | Select -Index 1; "^
"example break line further...."
powershell -command %function%
The ^ works as multiline character but it also escapes the first character, so also a quote would be escaped.
Do not mix batchfile syntax with PowerShell. As #Stephan mentioned $function= won't work in batch file. You need to use set function= instead. Let's say I want to execute the following:
Get-Process
Get-ChildItem
Then the code should look like this:
set function=Get-Process; ^
Get-ChildItem;
And you start PowerShell with:
powershell -noexit -command %function%
-noexit added so that you can verify that the code was successfully executed.
Also keep in mind that what you pass to PowerShell is batch multiline and in PowerShell it's visible as one line so you have to remember about semicolon (which you actually do but I'm leaving this comment here for future readers).
There's also another option how to pass variable from batch script to PowerShell. You can do it like this:
set name=explorer
set function=get-process $args[0]; ^
get-childitem
powershell -noexit -command "& {%function% }" %name%
Explanation:
$args[0] represents first argument passed to the scriptblock. To pass that argument, add %name% after the scriptblock while starting powershell. Also, as pointed out in this answer (credits to #Aacini for pointing this out in comments), you have to add & operator and keep your scriptblock inside curly brackets { }.
Sidenote: to be honest, I'd avoid running scripts like this. Much simpler way would be to just save the file as .ps1 and run this in your batch file:
powershell -noexit -file .\script.ps1

Replace single quote by two single quotes in a file with batch powershell command

I'm currently working on an automated setup program. It has to execute SQL command. I decided to create it with a simple batch file which allows me to use commands like sqlcmd or Powershell.
I'm working on a XML file that will get insert into another file. First, I have to replace some strings in it. I successfully used the -replace command like that :
powershell -Command "(gc source_file.xml) -replace 'utf-8', 'utf-16' | sc updated_file.xml"
Now, the updated_file.xml still contains single quotes that I'd like to replace by '' (two single quotes). I'd like to use the replace command again to make the substitution. I tried to escape the single quote character but it didn't work :
powershell -Command "(gc source_file.xml) -replace "`'", "`'`'" | sc updated_file.xml"
The error shows that the single quote isn't escaped. What's more, in my case, it seems that the replace command only reads string between single quotes. I also tried with a regex::Escape("`'") without success.
Do you have any idea ?
Thanks a lot !
try this:
powershell -Command "(gc source_file.xml) -replace 'utf-8', 'utf-16' -replace '''', '''''' | sc updated_file.xml"
For cmd.exe you have to escape inner double quotes with a backslash, so this should work:
powershell -NoP -C "(gc source_file.xml) -replace 'utf-8','utf-16' -replace \"'\",\"''\" | Set-Content updated_file.xml"
Hint: the alias sc is removed in upcoming releases of PowerShell, so avoid it.
Also changing content text utf8 => utf-16 won't change the encoding (possibly append -Encoding UTF8 to the gc.

Command to run PowerShell command from Windows CMD

Consider:
(Get-Content Rel_DDL.SQL) | ForEach-Object {
$_ -replace "SWIFT [\d\.]+", "SWIFT 2.4.0"
} | Set-Content Rel_DDL.SQL
The above PowerShell code replaces SWIFT 2.3.0 with SWIFT 2.4.0 in a SQL file, which when I run through PowerShell works fine.
I want to run the PowerShell command through Windows CMD, but I am getting errors.
You can use the Powershell.exe command in CMD Windows with the -command parameter. Did you try it?
-Command
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt, and then exits, unless
NoExit is specified. The value of Command can be "-", a string. or a
script block.
If the value of Command is "-", the command text is read from standard input.
If the value of Command is a script block, the script block must be enclosed in braces ({}).
You can specify a script block only when running PowerShell.exe in Windows PowerShell. The results of the script block are returned to the parent shell as deserialized XML objects, not live objects.
If the value of Command is a string, Command must be the last parameter in the command, because any characters typed after the command are interpreted as the command arguments.
To write a string that runs a Windows PowerShell command, use the format: "& {}" where the quotation marks indicate a string and the invoke operator (&) causes the command to be executed.
Use the powershell command in that .bat script. I would not write to the same file as used for the input. Yes, I know this works because Get-Content reads the entire file, but it is not a good practice.
powershell -NoProfile -Command "(Get-Content Rel_DDL.SQL) |" ^
"ForEach-Object { $_ -replace 'SWIFT [\d\.]+', 'SWIFT 2.4.0' } |" ^
"Out-File -FilePath Rel_DDL2.SQL -Encoding Default"

Powershell command -replace with multi-line value

I'm struggling to use powershell to replace a string with multi-line value.
The value is from Jenkins input text parameter. So this value is a multi-line string.
I use powershell to replace {{BUILD_INFO_CHANGES}} with %BUILD_INFO_CHANGES%.
The %BUILD_INFO_CHANGES% value is
-bug1
-bug 2
Here is the script:
powershell -Command "(gc %JOB_BUILD_DIR%\ThisBuildInfo.md) -replace '{{BUILD_INFO_CHANGES}}', '%BUILD_INFO_CHANGES%' | Out-File %JOB_BUILD_DIR%\ThisBuildInfo.md"
However, I got the error response from Jenkins.
'{{BUILD_INFO_FIXED_BUGS}}', <<<< '- bug1 is missing the terminator: '. ... + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
d
And I change the script and use # to wrap the value. Here is the changed script.
powershell -Command "(gc %JOB_BUILD_DIR%\ThisBuildInfo.md) -replace '{{BUILD_INFO_CHANGES}}', #'%BUILD_INFO_CHANGES%'# | Out-File %JOB_BUILD_DIR%\ThisBuildInfo.md"
I got another error.
FullyQualifiedErrorId : UnrecognizedToken
Does anyone have a solution for this?
thanks!
The problem is using the -Command parameter for anything other than a simple script you will run into issues where characters such as curly braces and quotes will be misinterpreted by the command prompt before the are they are passed to PowerShell. You could could tie yourself in knots by adding several layers of escaping or there is a simpler way - use the -EncodedCommand parameter instead.
For the -EncodedCommand you just need to Base64 encode your command which you can do with the following PowerShell script:
$command = #'
# Enter your commands containg curly braces and quotes here
# As long as you like
'#
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes) | clip.exe
This will copy the encoded command to the clipboard, then all you need to do to use your command is type:
powershell.exe -EncodedCommand
.. and then paste in your command so that you end up with something like the following:
powershell.exe -EncodedCommand IAAgACMAIABFAG4AdABlAHIAIAB5AG8AdQByACAAcwBjAHIAaQBwAHQAIABjAG8AbgB0AGEAaQBuAGcAIABjAHUAcgBsAHkAIABiAHIAYQBjAGUAcwAgAGEAbgBkACAAcQB1AG8AdABlAHMACgAgACAAIwAgAEEAcwAgAGwAbwBuAGcAIABhAHMAIAB5AG8AdQAgAGwAaQBrAGUAIAAgAA==
You now have something that is command prompt safe.
Thanks Dave! Your solution give me an idea.
Here is the easiest solution to work on Jenkins.
I put the following scripts on a Powershell build step in my Jenkins build job.
$thisBuildInfoPath="$env:JOB_BUILD_DIR\ThisBuildInfo.md"
$fixedBugs=#("$env:BUILD_INFO_FIXED_BUGS")
(gc $thisBuildInfoPath) -replace "{{BUILD_INFO_FIXED_BUGS}}", $fixedBugs | sc $thisBuildInfoPath