How to replace an unknown string? (only pattern is known) - php

I want to replace a string which might appear within a URL.
The string has the following pattern:
%26TID%3D123456
I want to replace the 123456 part, to a specific value such as: 777777.
To be on the safe side though, I don't want to assume that the relevant part of the original string has necessarily 6 digits after the %3D part; I want to assume that the original string might contain a few more or few less characters (and I also can't tell the real value of each digit).
In addition, when I replace the string, since that string will usually appear in the middle of the URL, I need to replace it without modifying the rest of the URL. After that string, there would usually be another %26 string which I want to keep including whatever that is after it, but to be on the safe side, I don't want to assume that the original string is necessarily followed by %26.
What is the best practice to make such a replacement, that would stand up to all my above conditions?

The general rule is to specify the boundary (or an "anchor") (here, a starting one) and then match whatever you want with the more generic pattern.
Here, the "anchor" is the literal text TID%3D. The more generic pattern is one or more digits: \d+.
Since you need to replace the first occurrence, you need to pass 1 as the limit argument value in preg_replace.
So, combining all that:
$re = '~TID%3D\d+~';
$str = "%26TID%3D123456 %26PID%3D123456 %26TID%3D123456";
$subst = 'TID%3D7652';
echo $result = preg_replace($re, $subst, $str, 1);
// = > %26TID%3D7652 %26PID%3D123456 %26TID%3D123456
See IDEONE demo
If you do not want (or do not know) the "anchor" text, use a capturing mechanism (demo):
$re = '~(TID%\w{2})\d+~'; // (...) specify a capturing group referenced with ${1} later
$str = "%26TID%3D123456 %26PID%3D123456 %26TID%3D123456";
$subst = '${1}7652';
echo $result = preg_replace($re, $subst, $str, 1);
// = > %26TID%3D7652 %26PID%3D123456 %26TID%3D123456
You can also use a lookbehind approach, but it is less efficient:
$re = '~(?<=TID%3D)\d+~'; // (?<=TID%3D) makes sure digits are preceded with TID%3D substring
$str = "%26TID%3D123456 %26PID%3D123456 %26TID%3D123456";
$subst = '${1}7652';
echo $result = preg_replace($re, $subst, $str, 1);

Related

RegEx for adding a space in a special pattern

Quick note: I know markdown parsers don't care about this issue. It's for the sake of visual consistency in the md file and also experimentation.
Sample:
# this
##that
###or this other
Goal: read each line and,if a markdown header does not have a space after the pound/hashtag sign, add one so that it would look like:
# this
## that
### or this other
My non-regex attempt:
function inelegantFunction (string $string){
$array = explode('#',$string);
$num = count($array);
$text = end($array);
return str_repeat('#', $num-1)." ".$text;
}
echo inelegantFunction("###or this other");
// returns ### or this other
This works, but it has no mechanism to match the unlikely case of seven '#'.
Regardless of efficacy, I would like to figure out how to do this with regex in php (and perhaps javascript if that matters).
Try to match (?m)^#++\K\S which matches lines starting with one or more number signs then replace it with $0 in your function:
return preg_replace('~(?m)^#++\K\S~', ' $0', $string);
See live demo here
To limit the number of #s to six use:
(?m)^(?!#{7})#++\K\S
I'm guessing that a simple expression with a right char-list boundary might be working here, maybe:
(#)([a-z])
If we might be having more chars, we can simply add it to [a-z].
Demo
Test
$re = '/(#)([a-z])/m';
$str = '#this
##that
###that
### or this other';
$subst = '$1 $2';
$result = preg_replace($re, $subst, $str);
echo "The result of the substitution is ".$result;

How to remove certain Part of JSON

Sorry for my bad English in Advance. Here is my JSON return.
https://images-na.ssl-images-amazon.com/images/M/MV5BYzc3OGZjYWQtZGFkMy00YTNlLWE5NDYtMTRkNTNjODc2MjllXkEyXkFqcGdeQXVyNjExODE1MDc#._V1_UY268_CR5,0,182,268_AL_.jpg
How can I remove the part UY268_CR5,0,182,268_AL_. Specifically that part only. And I have many of this links. Each having different strings there. For example:
https://m.media-amazon.com/images/M/MV5BYWNlMWMxOWYtZWI0Mi00ZTg0LWEwZTMtZTEzZDY0NzAxYTA4XkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_UX182_CR0,0,182,268_AL_.jpg
As shown it is different. I want to remove the part UX182_CR0,0,182,268_AL_. Each of the results I have has almost the same structure but the end part I want to remove. I am on laravel and so I am encoding my jsons result from controller. Is there anyone this can be done with php?
Update:
Here is the code I tried.
$json = json_decode($data,true);
$slice = str_replace("UY268_CR5,0,182,268_AL_","", $json);
return $slice ['poster'];
The string is removed but what about different strings with different URL's like mentioned above?
You can try with preg_replace() with the combination of lookahead and lookbehind
<?php
$re = '/(?<=_V1_)(.+?)(?=.jpg)/';
$str = 'https://m.media-amazon.com/images/M/MV5BYWNlMWMxOWYtZWI0Mi00ZTg0LWEwZTMtZTEzZDY0NzAxYTA4XkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_UX182_CR0,0,182,268_AL_.jpg';
$subst = '';
$result = preg_replace($re, $subst, $str, 1);
echo "The result of the substitution is ".$result;
?>
DEMO: https://eval.in/1044470
REFF: Regex lookahead, lookbehind and atomic groups
REGEX EXPLANATION: https://regex101.com/r/aHAw5f/1

Suggestion about search coincidences in string with PHP using REGEX

I am trying to search this coincidence in a string:
1. I need to take only numbers after the chracter '#' as long as this coincidence has not spaces, for example:
String = 'This is a test #VVC345RR, text, and more text 12345';
I want to take only this from my string -> 345.
My example:
$s = '\"access_token=103782364732640461|2. myemail#domain1.com ZmElnDTiZlkgXbT8e3 #DD234 4Jrw__.3600.1281891600-10000186237005';
$matches = array();
$s = preg_match('/#([0-9]+)/', $s, $matches);
print_r($matches);
This only works when I have one # and numbers.
Thanks!
Maybe:
#\D*\K(\d+)
Accomplishes what you want?
This will look for an #, any non-numbers, and then capture the numbers. The \K ignores the early match.
https://regex101.com/r/gNTccx/1/
I'm unclear what you mean by has not spaces, there are no spaces in the example string.

Encode equal sign in query string with regex

I have a query string that may look like one of the following:
?key=aa=bb
?key=aa=bb=cc
?key=aa=bb&key2=cc
etc.
What I want to do is replace the equal sign in the value part only. So it should result in this:
?key=aa%3dbb
?key=aa%3dbb%3dcc
?key=aa%3dbb&key2=cc
I'm trying to do that with the following regex by using a look ahead. But it's not doing anything.
echo preg_replace("/=(?=[^&])=/", "%3d", 'http://www.example.com?key=aaa=bbb=ccc&key3=dddd');
Example code here
How can I make this work?
(\bkey\d*)=(*SKIP)(*F)|=
Try this.See demo.
https://regex101.com/r/hR7tH4/13
$re = "/(\\bkey\\d*)=(*SKIP)(*F)|=/m";
$str = "\n ?key=aa=bb\n ?key=aa=bb=cc\n ?key=aa=bb&key2=cc\n";
$subst = "%3d";
$result = preg_replace($re, $subst, $str);
You don't need regex, use the proper tools. parse_url() to get the query string (and whatever else you want), then parse_str() to get an array of the var/vals. Then http_build_query() will encode for you:
$query = parse_url('http://www.example.com?key=aaa=bbb=ccc&key3=dddd', PHP_URL_QUERY);
parse_str($query, $array);
$result = http_build_query($array);
Here is another version of a regex based on the same approach as vks':
[&?][^&=]+=(*SKIP)(*FAIL)|=
Regex explanation:
[&?] - Match & or ? literally
[^&=]+ - Match characters other than & and =
= - Match = (so, we matched a key)
(*SKIP)(*FAIL) - Verbs that fail the match at this point (we do not replace this = we found after key)
= - We match any other = and we'll remove it.
Here is IDEONE demo:
$re = "/[&?][^&=]+=(*SKIP)(*FAIL)|=/";
$str = "http://google.com?key=aa=bb\nhttp://google.com?key=aa=bb=cc\nhttp://google.com?key=aa=bb&key2=cc";
$result = preg_replace($re, "%3d", $str);
echo $result;
What about this?
preg_replace_callback("/=([^&$]+)/", "myReplace", "http://www.example.com?key=aaa=bbb=ccc&key3=dddd");
function myReplace($matches) {
return "=" . urlencode($matches[1]);
}
Just gonna add an addendum, explaining your specific attempt:
preg_replace("/=(?=[^&])=/",
↑ ↑
While the lookahead was a nice idea, it really just would match a single character. And in this case just would have asserted the very next character not to be &.
You could refashion it into:
preg_replace("/=([^&=]+)\K=/",
↑
Which I guess is what you tried. Note that this merely ignores every second =………= equal sign. So would only suit your simple example query strings, not more plentiful unescaped characters within.

How to detect a string with specific pattern from a larger string?

I have a long string from which I want to detect and replace with some other text. Suppose my text is 'my first name is #[[Rameez]] and second name is #[[Rami]]'. I want to detect #[[Rameez]] and replace with Rameez dynamically to all likewise strings.
You could simply do:
preg_replace('/#\[\[(\w+)\]\]/', "$1", $string);
[ and ] need to be escaped because they have special meaning in a regex.
This will replace any string #[[whatever]] by whatever
Specific version
// Find Rameez specifically
$re = '/#\[\[(?<name>Rameez)\]\]/i'; // Use i flag if you to want a case insensitive search
$str = 'my first name is #[[Rameez]] and second name is #[[Rami]].\nDid I forget to mention that my name is #[[rameez]]?';
echo preg_replace($re, '$1', '**RAMEEZ** (specific)<br/>' . PHP_EOL);
Generic version
Regex
#\[\[(?<name>.+?)\]\]
Description
(?<name> .. ) represents here a named capturing group. See this answer for details.
Sample code
// Find any name enclosed by #[[ and ]].
$re = '/#\[\[(?<name>Rameez)\]\]/i'; // Use i flag if you to want a case insensitive search
$str = 'my first name is #[[Rameez]] and second name is #[[Rami]].\nDid I forget to mention that my name is #[[rameez]]?';
echo preg_replace($re, '$1', '**RAMEEZ** (generic)<br/>' . PHP_EOL);
DEMO
You can create a regex pattern then user it to match, find and replace a given string. Here's example:
string input = "This is text with far too much " +
"whitespace.";
string pattern = "\\s+";
string replacement = " ";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
It's C# code but you can apply it to any language really. In your case you can substitute the pattern with something like string pattern = "#[[Rameez]]"; and then use different replacement: string replacement = "Rameez";
I hope that makes sense.

Categories