preg_replace - how to escape "[" - preg-replace

I wrote this code:
<?
$text='how are you [b] today [/b]';
$patterns = array();
$patterns[0] = '/\[b/';
$patterns[1] = '/\b]/';
$replacements = array();
$replacements[1] = 'b]aaa<>';
$replacements[0] = '<>aaa[b';
ksort($patterns);
ksort($replacements);
echo preg_replace($patterns, $replacements, $text);
echo "_";
echo $text;
echo "_";
echo "END";
?>
the output shows:
how are you <>aaa[bb]aaa<> today [/b]aaa<>______how are you [b] today [/b]______END
but the output should be:
how are you <>aaa[b] today [/b]aaa<>______how are you [b] today [/b]______END
what did I do wrong? Please help. Thank you

You need to double-escape the brackets:
$patterns[0] = '/\\[b/';
A single backslash will be "consumed" by PHP when it parses the string, leaving just a bare [, which will be seen by the regex engine as the beginning of a character class. By double-escaping, the \\ will be seen by PHP as an escape, leaving a single \, which will be seen by the regex engine as an escape.

Your problem has nothing to do with escaping [. Your problem is that you want $patterns[1] to only match "/b]" but that's not what you wrote in your regular expression.
Try '/\/b]/' instead, or use alternate delimiters (e.g. '!/b]!') to avoid leaning-toothpick syndrome.

Related

Powershell - Remove text and capitalise some letters

Been scratching my head on this one...
I'd like to remove .com and capitalize S and T from: "sometext.com"
So output would be Some Text
Thank you in advance
For most of this you can use the replace() member of the String object.
The syntax is:
$string = $string.replace('what you want replaced', 'what you will replace it with')
Replace can be used to erase things by using blank quotes '' for the second argument. That's how you can get rid of .com
$string = $string.replace('.com','')
It can also be used to insert things. You can insert a space between some and text like this:
$string = $string.replace('et', 'e t')
Note that using replace does NOT change the original variable. The command below will print "that" to your screen, but the value of $string will still be "this"
$string = 'this'
$string.replace('this', 'that')
You have to set the variable to the new value with =
$string = "this"
$string = $string.replace("this", "that")
This command will change the value of $string to that.
The tricky part here comes in changing the first t to capital T without changing the last t. With strings, replace() replaces every instance of the text.
$string = "text"
$string = $string.replace('t', 'T')
This will set $string to TexT. To get around this, you can use Regex. Regex is a complex topic. Here just know that Regex objects look like strings, but their replace method works a little differently. You can add a number as a third argument to specify how many items to replace
$string = "aaaaaa"
[Regex]$reggie = 'a'
$string = $reggie.replace($string,'a',3)
This code sets $string to AAAaaa.
So here's the final code to change sometext.com to Some Text.
$string = 'sometext.com'
#Use replace() to remove text.
$string = $string.Replace('.com','')
#Use replace() to change text
$string = $string.Replace('s','S')
#Use replace() to insert text.
$string = $string.Replace('et', 'e t')
#Use a Regex object to replace the first instance of a string.
[regex]$pattern = 't'
$string = $pattern.Replace($string, 'T', 1)
What you're trying to achieve isn't well-defined, but here's a concise PowerShell Core solution:
PsCore> 'sometext.com' -replace '\.com$' -replace '^s|t(?!$)', { $_.Value.ToUpper() }
SomeText
-replace '\.com$' removes a literal trailing .com from your input string.
-replace '^s|t(?!$), { ... } matches an s char. at the start (^), and a t that is not (!) at the end ($); (?!...) is a so-called negative look-ahead assertion that looks ahead in the input string without including what it finds in the overall match.
Script block { $_.Value.ToUpper() } is called for each match, and converts the match to uppercase.
-replace (a.k.a -ireplace) is case-INsensitive by default; use -creplace for case-SENSITIVE replacements.
For more information about PowerShell's -replace operator see this answer.
Passing a script block ({ ... }) to dynamically determine the replacement string isn't supported in Windows PowerShell, so a Windows PowerShell solution requires direct use of the .NET [regex] class:
WinPs> [regex]::Replace('sometext.com' -replace '\.com$', '^s|t(?!$)', { param($m) $m.Value.ToUpper() })
SomeText

how do I replace a string with a dollar sign in it in powershell

In Powershell given the following string
$string = "this is a sample of 'my' text $PSP.what do you think"
how do I use the -replace function to convert the string to
this is a sample of 'my' text Hello.what do you think
I obviously need to escape the string somehow, Also $PSP is not a declared variable in my script
I need to change all mentions of $PSP for some other string
Use the backtick character (above the tab key):
$string = "this is a sample of 'my' text `$PSP.what do you think"
To replace the dollar sign using the -replace operator, escape it with backslash:
"this is a sample of 'my' text `$PSP.what do you think" -replace '\$PSP', 'hello'
Or use the string.replace method:
$string = "this is a sample of 'my' text `$PSP.what do you think"
$string.Replace('$PSP','Hello)'
this is a sample of 'my' text Hello.what do you think
Unless you modify your original string (e.g. by escaping the $), this is isn't (really) possible.
Your $string doesn't really contain a $PSP, as it is replaced by nothing in the assignment statement.
$string = "this is a sample of 'my' text $PSP.what do you think"
$string -eq "this is a sample of 'my' text .what do you think"
evaluates to:
True
This comes up as the first answer in google even though it is really old, so I will add my slight variation.
In my case I was reading in a file and replacing a string with $s in it.
The short version of my file is:
<version>$version$<version>
In the case where one is actiong on a (file) stream, variables are not autoreplaced so there is no need to escape the $ in the file.
In the replacement pattern you can avoid the interpretation of the variable using ' instead of ".
My final command looked like:
(gc $fileName) | % { $_.replace('$version$', "$BuildNumber") } | sc $fileName
This is a file read(get-content) piped through the replace and back in to the file with a set-content.
You should try
$string = $string.Replace("\$PSP", "Hello")
or
$string = $string.Replace("\$PSP", $the_new_value)
or to be more generic use Regex
$string = [regex]::Replace($string, "\$\w+", "Hello")

encode special character in html entities in perl

I have a string where special characters like ! or " or & or # or #, ... can appear. How can I convert in the string
str = " Hello "XYZ" this 'is' a test & so *n #."
automatically every special characters with their html entities, so that I get this:
str = " Hello &quot ;XYZ&quot ; this &#39 ;is&#39 ; a test &amp ; so on #"
I tried
$str=HTML::Entities::encode_entities($str);
but it does a partial work the # is not transformed in &#64 ;
SOLUTION:
1) with your help (Quentin and vol7ron) I came up with this solution(1)
$HTML::Entities::char2entity{'#'} = '#';
$HTML::Entities::char2entity{'!'} = '!';
$HTML::Entities::char2entity{'#'} = '#';
$HTML::Entities::char2entity{'%'} = '%';
$HTML::Entities::char2entity{'.'} = '.';
$HTML::Entities::char2entity{'*'} = '*';
$str=HTML::Entities::encode_entities($str, q{#"%'.&#*$^!});
2) and I found a shorter(better) solution(2) found it here:
$str=HTML::Entities::encode_entities($str, '\W');
the '\W' does the job
#von7ron with solution(1) you will need to specify the characters you want to translate as Quentin mentioned earlier even if they are on the translation table.
# isn't transformed because it isn't considered to be a "special character". It can be represented in ASCII and has no significant meaning in HTML.
You can expand the range of characters that are converted with the second argument to the function you are using, as described in the documentation.
You can manually add a character to the translation table (char2entity hash).
$HTML::Entities::char2entity{'#'} = '#';
my $str = q{ Hello "XYZ" this 'is' a test & so on #};
my $encoded = HTML::Entities::encode_entities( $str, q{<>&"'#} );
The above adds #, which will be translated to #.
You then need to specify the characters you want to translate, if you don't it uses <>&", so I added both # and '. Notice, I didn't have to add the ' to the translation table, because it's already there by default.
You don't need to add ASCII characters (0-255) to the char2entity hash, since the module will do it automatically.
Note: Setting the char2entity for #, was done as an example. The module automatically sets numerical entities for ASCII characters (0-255) that weren't found. You'd have to use it for unicode characters, though.
Cheap, dirty, and ugly, but works:
my %translations;
$translations{'"'} = '&quot ;';
$translations{'\''} = '&#39 ;';
etc...
sub transform()
{
my $str = shift;
foreach my $character (keys(%translations))
{
$str =~ s/$character/$translations{$character}/g;
}
return $str;
}

How to replace a $ in a string in perl script

I have a string,
$str = abc#$and#def
I tried to replace '$' with it's hex value using ,
$str=~s/$/%26/g
But the output is abc#.
This might be because '$'is considered as the end of the line or string.
Please let me know
Your problem is nothing to do with your substitution; when you are assigning to the string in the first place:
$str = "abc#$and#def";
$and and #def are treated as variables to interpolate.
You need to escape the sigils or use single quotes (which don't interpolate variables):
$str = 'abc#$and#def';
# or
$str = "abc#\$and\#def";
And you really really need to enable warnings, which would have told you your assignment was the problem.
You need to escape the $ with a \
$str =~ s/\$/%26/g
Try escaping the $ with a \:
$str =~ s/\$/%26/g;
Ron

How can I manually interpolate string escapes in a Perl string?

In perl suppose I have a string like 'hello\tworld\n', and what I want is:
'hello world
'
That is, "hello", then a literal tab character, then "world", then a literal newline. Or equivalently, "hello\tworld\n" (note the double quotes).
In other words, is there a function for taking a string with escape sequences and returning an equivalent string with all the escape sequences interpolated? I don't want to interpolate variables or anything else, just escape sequences like \x, where x is a letter.
Sounds like a problem that someone else would have solved already. I've never used the module, but it looks useful:
use String::Escape qw(unbackslash);
my $s = unbackslash('hello\tworld\n');
You can do it with 'eval':
my $string = 'hello\tworld\n';
my $decoded_string = eval "\"$string\"";
Note that there are security issues tied to that approach if you don't have 100% control of the input string.
Edit: If you want to ONLY interpolate \x substitutions (and not the general case of 'anything Perl would interpolate in a quoted string') you could do this:
my $string = 'hello\tworld\n';
$string =~ s#([^\\A-Za-z_0-9])#\\$1#gs;
my $decoded_string = eval "\"$string\"";
That does almost the same thing as quotemeta - but exempts '\' characters from being escaped.
Edit2: This still isn't 100% safe because if the last character is a '\' - it will 'leak' past the end of the string though...
Personally, if I wanted to be 100% safe I would make a hash with the subs I specifically wanted and use a regex substitution instead of an eval:
my %sub_strings = (
'\n' => "\n",
'\t' => "\t",
'\r' => "\r",
);
$string =~ s/(\\n|\\t|\\n)/$sub_strings{$1}/gs;