Escape double quotes and single quotes in Jenkins pipeline script - powershell

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.

Related

Remove Orphaned Carriage Returns from File

I have a daily process that downloads and parses pipe-delimited files into a database. Sometimes these files contain a single carriage return (no newline) at the end of one of the fields within a row, which breaks my process. My scheduler (not a windows scheduler, internal to our company) allows me to run batch or PowerShell processes on these files before loading them into the database, so I want to trim out any instance of orphaned carriage returns at the end of a field (\r|).
This PowerShell command works when run manually:
(Get-Content CarriageReturnTest.txt -Raw).Replace("`r|","|") | Set-Content CarriageReturnTest.txt -Force
However when I put this in the scheduler, I get an error that '","' is not recognized as an internal or external command. I realized the scheduler must be running a windows command of PowerShell "{command}" so the double quotes are making the command line think that I'm running several different commands. I tried replacing the double quotes in the PowerShell command with single quotes like so:
(Get-Content CarriageReturnTest.txt -Raw).Replace('`r|','|') | Set-Content CarriageReturnTest.txt -Force
This runs through the scheduler, but doesn't actually trim anything out of the file because PowerShell interprets the ` as an escape character when it's enclosed in single quotes.
I've tried escaping the double quotes with "", `", \", and ^" but nothing seems to work.
I realize there's some longer batch scripts I could write to handle this but ideally this would be a one liner to fit in the scheduler. I've also looked into saving the script as a ps1 file and running that with the file paths as arguments but I haven't gotten that to work either.
Based off what #JosefZ said I tried this and it worked:
(Get-Content CarriageReturnTest.txt -Raw) -replace('\r\|','|') | Set-Content CarriageReturnTest.txt -Force
The -replace let me use regex in single quotes '\r' instead of "`r"in double, which kept me from escaping

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.

Powershell v2: Replace CRLF with LF

Using Powershell v2 called from a batch file, I want to replace each CRLF in a file with just an LF. If a file only has LF without any CR, then I want all the LF to be left alone.
I do not want a terminating CRLF in the resultant file, if possible.
I found this question here on Stack Overflow, that seems to be a close match, but it does not specify a Powershell version requirement, nor does it specify the other criteria above. Hence this question.
The accepted answer for that question recommends this code:
$in = "C:\Users\abc\Desktop\File\abc.txt"
$out = "C:\Users\abc\Desktop\File\abc-out.txt"
(Get-Content $in) -join "`n" > $out
I slightly modified it, and adjusted it to work from within a batch file, to read:
powershell -Command "(Get-Content file1.txt) -join '`n' > file2.txt"
Unfortunately, this does not work. All LF's are converted to the string `n.
How can I get this to work?
Those before me are right you should use "`n"
When using PowerShell I recommend executing it the following switches:
-noninteractive indicate you do not want to interact with the powershell
-NoProfile - speeds up the things considerably (skips loading profile)
-ExecutionPolicy Bypass - bypasses security issues if you are on companies environment
Edit:
Sorry about the mistake you mentioned. I now have PowerShell 2.0 testing facility.
The fixed your example (the mistake was that you have to escape the double quotes due to the powershell.exe interpreting them). This approach does not work completely as it leaves CRLF at the end of the file:
powershell.exe -noninteractive -NoProfile -ExecutionPolicy Bypass -Command "& {(Get-Content file_crlf.txt) -join \"`n\" > file_lfonly.txt};"
However, the completely correct solution needs different approach (via IO.file class):
powershell.exe -noninteractive -NoProfile -ExecutionPolicy Bypass -Command "& {[IO.File]::WriteAllText('file_lfonly.txt', ([IO.File]::ReadAllText('file_crlf.txt') -replace \"`r`n\", \"`n\"))};"
This completely converts your CRLF to LF. Just small piece of warning it converts to ASCII not Unicode (out of scope of this question).
All examples are now tested on PowerShell v2.0.50727.
A couple of things:
Single quotes ' are literal - use double quotes " so that PowerShell knows you mean new line
If you need to escape double quotes within double quotes, use "" or `"
Edit:
Your original post worked for me, so looks like this is related to PowerShell 5 v 2, and I am unable to test the solution. Instead of escape characters, here is a solution using scriptblock:
powershell -Command {(Get-Content file1.txt) -join "`n" > file2.txt}
It's worth noting that this is trivial in Notepad++ and can be done for multiple files at once:

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

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.

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