Difficulty escaping quote character in powershell script (Azure Devops Yaml) - powershell

My azure piplines yaml script uses powershell to replace a placeholder string in a .CS file with the current date string. This is the line with the value to be replaced (20200101000000)
[assembly: MyCompany.Net.Attributes.BuildDateAttribute("20200101000000")]
This is the powershell step that does it
pwsh: (get-content -path $(versionFile)) | foreach-object {$_ -replace "20200101000000", (get-date -f 'yyyyMMddhhmmss')} | set-content -path $(versionFile)
displayName: 'Update time stamp file'
I want to alter this step to include the quote characters " around the search string and write them into the new output value along with the new date. But I cannot seem to make that happen.
I mistakenly tried just putting escaped quote characters \" in the search and replace strings. But I guess you cannot escape inside of a single-quoted string so it did not work
pwsh: (get-content -path $(versionFile)) | foreach-object {$_ -replace "\"20200101000000\"", (get-date -f '\"yyyyMMddhhmmss\"')} | set-content -path $(versionFile)
This was the error:
##[command]"C:\Program Files\PowerShell\7\pwsh.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'D:\a\_temp\80625e52-1302-4e35-a799-223ab893bcf1.ps1'"
ParserError: D:\a\_temp\80625e52-1302-4e35-a799-223ab893bcf1.ps1:3
Line |
3 | … lyInfo.cs) | foreach-object {$_ -replace "\"20200101000000\"", (get-d …
| ~~~~~~~~~~~~~~~~~
| Unexpected token '20200101000000\""' in expression or statement.
##[error]PowerShell exited with code '1'.
I also tried to just using double quotes around the get-date part of the script so I could escape the quote characters but that doesn't seem to work either. I'm guessing that's a limitation of writing script this way.
Is there some other way to achieve what I want?

The escape character in Powershell is backtick (`), not backslash (\). Try e.g. "`"20200101000000`"".

You can use the Get-Date -UFormat instead to add arbitrary characters similar to the DateTime.ToString() function in .NET
'[Attrib("20200101000000")]' -replace '"20200101000000"', (get-date -UFormat '"%Y%m%d%H%M%S"')

Related

Replace Vertical bar within a text file

I am trying to replace a | character within a text file. But I am not sure how to do it because the batch is not reading the |.
powershell -Command "(gc output.txt) -replace '|', ' ' | Out-File -encoding ASCII output.txt"
Which takes this input:
80853||OHNED|Mira
And outputs: 8 0 8 5 3 | | O H N E D | M i r a
Where I'd like this output 80853 OHNED Mira
Is there anyway within a batch to replace the | character?
Edit - While googling, I found out that the | character is called a vertical bar.
PowerShell's -replace operator is regex-based; since your intent is to replace all | characters verbatim, you must escape | as \|, given that | is a regex metacharacter (a character with special meaning in the context of a regex (regular expression)):
powershell -Command "(gc output.txt) -replace '\|', ' ' | Out-File -encoding ASCII output.txt"
In cases where escaping individual characters isn't an option or would be cumbersome - e.g. if you're given a search string that you want to treat literally, as a whole - use [regex]::Escape():
powershell -Command "(gc output.txt) -replace [regex]::Escape('|'), ' ' | Out-File -encoding ASCII output.txt"
Alternatively, in your simple case you could use the .Replace() string method, which invariably performs verbatim replacements and therefore does not require escaping:
powershell -Command "(gc output.txt).Replace('|', ' ') | Out-File -encoding ASCII output.txt"
Note:
Unlike PowerShell's operators, the [string] type's .Replace() method is case-sensitive, invariably so in Windows PowerShell, and by default in PowerShell (Core) 6+.
See also:
For general guidance on when to use PowerShell's -replace operator vs. the .NET [string] type's .Replace() method, see the bottom section of this answer.
For robustly escaping all metacharacters in a -replace search regex and/or in its replacement operand in order to treat one or both as verbatim strings, see this answer.
Edit : This can did the trick to replace the special char :
#echo off
powershell -Command "(gc input.txt -raw) -replace '([\^&<>\|\(\)!])', ' ' | Out-File output.txt"
start "" output.txt

Powershell -Replace command and escaping characters

I need to replace some strings multiple text files. I am running into an issue with the following string though. I tried escaping with a backtick ` before any special characters, but no luck, or maybe the backtick isn't in the right place.
I want to replace
Signal\s+:\s+',''
with
Signal\s+:\s+','';if (!`$signal) {`$signal='n/a'}
This is the string in the command that i am having a problem finding --> Signal\s+:\s+',''
Here is the powershell command i am using..
Get-ChildItem "f:\temp\*.ps1" | ForEach-Object -Process {(Get-Content $_) -Replace "Signal\s+:\s+',''" , "Signal\s+:\s+','';if (!`$signal) {`$signal='n/a'}" | Set-Content $_}
thank you
i just needed to escape the \ in the replace text.. thats all
-Replace "Signal\\s\+:\\s\+',''"
thanks

Path issue with passing a command from Autohotkey to PowerShell

Mypath := "C:\temp\example1.txt"
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
The above works just fine, content is copied to the clipboard by PowerShell but when I do the same thing but with a file that has a space in its file name it fails to run in PowerShell.
Running below
Mypath := "C:\temp\example 1.txt"
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
I get this error in PowerShell
Get-Content : A positional parameter cannot be found that accepts argument '1.txt'.
I have also tried to use double quotes on each side and use Autohotkeys escape symbol like so:
Mypath = "`"C:\temp\example 1.txt`""
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
As well as
Mypath = ""C:\temp\example 1.txt""
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
But on both occasions, PowerShell throws this error;
The string is missing the terminator: ".
What am I doing wrong? any help would be appreciated.
This is quite weird but it is possible to get it working. It's really one escape hell.
Lets go through what's wrong with each of your attempts.
Mypath := "C:\temp\example 1.txt"
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
Here you're not using the legacy syntax to assign a value to the variable Mypath, as you should.
It's a good thing to not be using the legacy syntax anymore.
However, since you're not using the legacy syntax, and are using the modern assigning operator :=(docs), you don't have any extra quotes " around the string.
So you're executing PowerShell with the following switches:
-command "get-content -path C:\temp\example 1.txt | Set-Clipboard".
And as you were able to guess, this is wrong because your filename is not quoted.
Mypath = "`"C:\temp\example 1.txt`""
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
Here you're again using legacy syntax. So any string is interpreted literally. Therefore, firstly there is no reason to try to escape the quotes ", and secondly you don't escape quotes in AHK with `.
So, in this attempt you're executing PowerShell with the following switches:
-command "get-content -path ""C:\temp\example 1.txt"" | Set-Clipboard".
And this is no good, because first ""s get evaluated to a single ", and then you have
-command "get-content -path "C:\temp\example 1.txt" | Set-Clipboard"
which has unescaped quotes " inside another quotes, so that's no good.
Mypath = ""C:\temp\example 1.txt""
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
And then here you have the exact same issue as in the previous one. Because, as we established, you don't escape quotes with `. This code is the exact same as the one above.
So, how should it be done?
You either need one more pair of escaped quotes " around the file path, or then just use a single quote for the inner quotes.
So in legacy syntax you'd want either:
Mypath = """"C:\temp\example 1.txt""""
Run, powershell -command "get-content -path %Mypath% | Set-Clipboard"
or
Mypath = 'C:\temp\example 1.txt'
Run, powershell -noexit -command "get-content -path %Mypath% | Set-Clipboard"
And in the modern expression syntax, you'd want either:
Mypath := """""""""C:\temp\example 1.txt"""""""""
Run, % "powershell -noexit -command ""get-content -path " Mypath " | Set-Clipboard"""
or
Mypath := "'C:\temp\example 1.txt'"
Run, % "powershell -noexit -command ""get-content -path " Mypath " | Set-Clipboard"""

How can i run multiple replace commands from one line of batch file

I have minimum to none knowledge of powershell :(
Hi I have two possible options to replace text from an .ini file, one is a menu-style batch, where choosing an option will execute a command.
My problem is: if I use the batch code I can only change a known resolution, because I don't know how to add multiple replace actions so they work if one fails.
The Powershell code does executes MULTIPLE replace commands, but I don't know how to edit it to use it as a batch command (powershell -command etc.)
Thank you in advance :)
Batch script:
#echo off
set ffile='resolutions.ini'
set HDReady='/resolution:1280,720'
set FullHD='/resolution:1920,1080'
set QuadHD='/resolution:2560,1440'
set UltraHD='/resolution:3840,2160'
powershell -Command "(gc %ffile%) -replace %hdready%, %fullhd% | Out-File %ffile% -encoding utf8"
Powershell script:
$original_file = 'path\resolutions.ini'
$destination_file = 'path\resolutions.ini'
(Get-Content $original_file) | Foreach-Object {
$_ -replace '/resolution:1280,720', '/resolution:1920,1080' `
-replace '/resolution:2560,1440', '/resolution:1920,1080' `
-replace '/resolution:3840,2160', '/resolution:1920,1080'
} | Set-Content $destination_file
Is one (1) line what you really want?
(Get-Content 'path\resolutions.ini') | Foreach-Object {$_ -replace '/resolution:1280,720', '/resolution:1920,1080' -replace '/resolution:2560,1440', '/resolution:1920,1080' -replace '/resolution:3840,2160', '/resolution:1920,1080'} | Set-Content 'path\resolutions.ini'
or
$original_file = 'path\resolutions.ini'; $destination_file = 'path\resolutions.ini'; (Get-Content $original_file) | Foreach-Object {$_ -replace '/resolution:1280,720', '/resolution:1920,1080' -replace '/resolution:2560,1440', '/resolution:1920,1080' -replace '/resolution:3840,2160', '/resolution:1920,1080'} | Set-Content $destination_file
You can also place your script in a file and run it as such:
powershell.exe -file My\FilePath.ps1
Here is the help section from the powershell executable:
PowerShell -Help
-File
Runs the specified script in the local scope ("dot-sourced"), so that the
functions and variables that the script creates are available in the
current session. Enter the script file path and any parameters.
File must be the last parameter in the command, because all characters
typed after the File parameter name are interpreted
as the script file path followed by the script parameters.

Script to replace line that contains text

I found another discussion on this, where there were numerous different options available but most of them didn't seem to work for myself or the original poster. I did however find an example that is confirmed working, however I am struggling with getting it to work and hoping for help.
I need to find a line that begins with "ServerName=" and replace this with my own line. I have used the example that was found and modified it, but I am getting errors when using it.
PowerShell Command:
powershell -Command "(Get-Content 'KFGame\Config\PCServer-KFGame.ini') | Foreach-Object {$_ -replace '^ServerName.$', ('ServerName=Network BUF 12345 Normal')} | Set-Content 'KFGame\Config\PCServer-KFGame.ini'"
Error Message:
) was unexpected at this time
If you want to run complex PowerShell statements from CMD you need to put them in quotes so that CMD just sees a string and doesn't try to handle special characters (like pipes):
powershell -Command "(Get-Content 'C:\Host400.txt') | Foreach-Object {$_ -replace '^workstationID.*$', (""WorkstationID=$computerName""} | Set-Content 'C:\Host400.txt'"
Note that you need to either escape or replace double quotes within the command string.
A better approach is to put the PowerShell statement(s) into a .ps1 script and run that via the -File parameter:
powershell -File "C:\path\to\your.ps1"