How to use $_ in content without been replaced by powershell? - regex

I'm trying to replace a word to some php code
$filecontent = [regex]::Replace($filecontent, $myword, $phpcode)
But the $phpcode have some php code using also a Special variable $_
<?php $cur_author = (isset($_GET['author_name'])) ? get_user_by('slug', $author_name) : get_userdata(intval($author)); ?>
The problem is when the code is replace in $filecontent it replaces the $_ variable from the php code ( $_GET ) with it have on the pipeline.
This not happen with the other variables like $author_name .
How can I resolve this?

Does this work for you?
$filecontent = [regex]::Replace($filecontent, $myword, {$phpcode})
In a regex replace operation the $_ is a reserved substituion pattern that represents the entire string
http://msdn.microsoft.com/en-us/library/az24scfc.aspx
Wrapping it in braces makes it a scriptblock delegate, bypassing the normal regex pattern matching algorithms for doing the replacement.

You have two options. First use a single quoted string and PowerShell will treat that as a verbatim string (C# term) i.e. it won't try to string interpolate:
'$_ is passed through without interpretation'
The other option is to escape the $ character in a double quoted string:
"`$_ is passed through without interpretation"
When I'm messing with a regex I will default to using single quoted strings unless I have a variable that needs to be interpolated inside the string.
Another possibility is that $_ is being interpreted by regex as a substitution group in which case you need to use the substitution escape on the $ e.g. $$.

Im not sure I am following you correctly, but does this help?
$file = path to your file
$oldword = the word you want to replace
$newword = the word you want to replace it with
If the Oldword you are replacing has special charactes ( ie. \ or $ ) then you must escape them first. You can escape them by putting a backslash in front of the special character. The Newword, does not need to be escaped. A $ would become "\$".
(get-content $file) | foreach-object {$_ -replace $oldword,$NewWord} | Set-Content $file

Related

How do you use a variable in a regex replace statement [duplicate]

$file = 'c:\temp\config.ini'
# login.ruby.authentication.key=eskimopie
$pattern = [regex] "(.*?login\.ruby\.authentication\.key)=(.*?).*"
$secret = '12345678'
$text = (Get-Content -Path c:\temp\config.ini)
$value = $text -match "$pattern"
$text -replace "$pattern",'$1=$secret' | Set-Content config.new
The problem is it replaces the line with
login.ruby.authentication.key)=$secret (in that, it actually puts $secret instead of 12345678. I am looking for how to get this to put the value of $secret instead of the word $secret.
When used inside single quoted literals, variables do not get expanded. You need to use double quoted string literal that allows string interpolation.
However, the first $ should not be expanded. To tell PS not to interpolate it, add a backtick before it. See about_Quoting_Rules:
To prevent the substitution of a variable value in a double-quoted string, use the backtick character (`)(ASCII 96), which is the Windows PowerShell escape character.
So, replace with "`$1=$secret" where `$1 will pass a literal $1 string to the regex engine, and $secret will get interpolated to 12345678 before passing it to the regex engine.

powershell regex displaying variable name instead of its value during replace

$file = 'c:\temp\config.ini'
# login.ruby.authentication.key=eskimopie
$pattern = [regex] "(.*?login\.ruby\.authentication\.key)=(.*?).*"
$secret = '12345678'
$text = (Get-Content -Path c:\temp\config.ini)
$value = $text -match "$pattern"
$text -replace "$pattern",'$1=$secret' | Set-Content config.new
The problem is it replaces the line with
login.ruby.authentication.key)=$secret (in that, it actually puts $secret instead of 12345678. I am looking for how to get this to put the value of $secret instead of the word $secret.
When used inside single quoted literals, variables do not get expanded. You need to use double quoted string literal that allows string interpolation.
However, the first $ should not be expanded. To tell PS not to interpolate it, add a backtick before it. See about_Quoting_Rules:
To prevent the substitution of a variable value in a double-quoted string, use the backtick character (`)(ASCII 96), which is the Windows PowerShell escape character.
So, replace with "`$1=$secret" where `$1 will pass a literal $1 string to the regex engine, and $secret will get interpolated to 12345678 before passing it to the regex engine.

Use Variable in Replace

I have a text file and want to regex/replace something with the content of a variable in PowerShell.
File: my.json
Variable in Powershell $version
Search for: version : "something"
Replace "something" with the content of the variable $version
Here is what I tried. Search and replace works as expected but the result is
version : "$version".
(Get-Content my.json) -replace '(?<pre>"version"[\s]*:[\s]*)(?<V>"[^\"]*")', '$1"$version"' | Out-File my.json
To be able to use variables in the replacement string you need to use a double-quoted replacement string, meaning that you need to escape backreferences and nested double quotes:
(Get-Content my.json) -replace '...', "`$1`"$version`"" | ...
Ansgar's answer is perfectly valid, but ` escape sequences can be ugly and hinder readability.
I would personally use the -f format operator to concatenate the '$1' string literal and the value of $version:
(Get-Content my.json) -replace '...',('$1{0}' -f $version)

Powershell - Replacing a string with a variable ending with a dollar sign

I'm a bit lost with this one. For whatever reason the replace function in powershell doesn't play well with variables ending with a $ sign.
Command:
$var='A#$A#$'
$line=('$var='+"'"+"'")
$line -replace '^.+$',('$line='+"'"+$var+"'")
Expected output:
$line='A#$A#$'
Actual output:
$line='A#$A#
It looks like you're getting hit with a regex substitution that you don't want. The regex special variable $' represents everything after your match. Since your regex matches the entire string, $' is effectively empty. During the replace operation, the .Net regex engine sees $' in your expected output and substitutes in that empty string.
One way to avoid this is to replace all instances of $ in your $var string with $$:
$line -replace '^.+$',('$line='+"'"+($var.Replace('$','$$'))+"'")
You can see more information about regex substitution in .Net here:
Substitutions
I was able to find a band-aid of sorts by replacing $ with a special character and then reverting it back after the change. Preferably you would choose a character that doesn't have a key on your keyboard. For me I chose "¤".
$var='A#$A#$'
$var=$var -replace '\$','¤'
$line=("`$var=''")
$line -replace '^.+$',("`$line='$var'") -replace '¤','$'
I don't really understand the purpose of your posted lines, it seems to me that it would just make more sense to do $line='$line='''+$var+"'", BUT if you insist on your way, just do two replace calls, like this:
$line -replace '^.+$',('$line=''LOL''') -replace 'LOL',$var

How to ignore escape sequences stored in PowerShell string variable?

In my PowerShell script, I'm running Select-String over a number of files, looking for a string passed into it via a variable ($id):
foreach ($file in (ls "path\to\files")) {
$found = $false
$found = Select-String -Path $file $id -Quiet
if ($found) {
break
}
}
Unfortunately, the $id variable sometimes things like "\C" or "\T", which Select-String tries to interpret as escape sequences. These are not valid escape sequences, so Select-String throws an error. They are not intended to be escape sequences (e.g., it could be part of a file path such as "C:\Test"), so how can I prevent PowerShell/Select-String from interpreting them as such? I've tried using parentheses around $id with no luck.
Use the static escape() method, it instructs the regular expression engine to interpret these characters literally rather than as metacharacters:
$id = [regex]::escape($id)
You can also turn the command to a one liner (-path can take a collection of files):
Select-String -Path path\to\files\\* -Pattern ([regex]::escape($id)) -Quiet
Select-String has a -SimpleMatch parameter that will cause the cmdlet to do simple string matches instead of regular expressions. If you change the script to do:
$found = Select-String -Path $file $id -Quiet -SimpleMatch
it should work as desired.
If the $id string already contains something like TAB when it's passed to you then I'm not aware of a built in method to safely escape it back to "\t". You need to make sure your script is passed the correct string in the first place. I.e. it needs to passed 0x5C74 (\t) not 0x09 (TAB). So the escaping needs to be done when the the search string is first defined.
Regex.Escape will escape TAB -> \t but will also escape any of these characters that have meaning within regular expressions:
\, *, +, ?, |, {, [, (,), ^, $,., #, and white space
e.g. . -> \.