Using preg_replace $limit randomly throughout string, not just first $limit matches? - php

I'm looking to preg_replace parts of a string only 3 times, however I don't want it to match and replace only the first 3 matches, but rather more varied throughout the entire string. Is this possible?
Example:
$post ['post_content']=preg_replace ('/ pizza /',' pizza ',$post['post_content'],3);

Use something like this (some tweaking might be needed):
$p = $post ['post_content'];
if (preg_match_all('/ pizza /',$p, $matches)) {
$rand = array_rand($matches[0], 2);
foreach($rand as $rand_key) {
$p=replace_num($matches[0][$rand_key], "XXX",$p, $rand_key+1);
}
}
echo $p;
function replace_num($from, $to, $string,$num) {
$pos=-1;
$i=0;
while($pos!==false && $i<$num) {
$pos = strpos($string, $from, $pos+1);
$i++;
}
if ($pos) {
return substr($string, 0, $pos) . str_replace($from, $to, substr($string,$pos, strlen($from))) . substr($string, $pos) ;
}
return $string;
}

I think you could do it. But it will be a multi-step process.
First: Do a preg_match_all() instead of a replace
Second: Do X number of array_rands to get the position of the 'pizza' string and replace one starting at that position (use substring).
I think you'll have to redo the match after each replacement, because the length of the string will change every time.
Don't forget to remove the index that is returned from the array rand so it isn't used twice.

Skip the 4th parameter which is to limit n go thru the manual first
$limit:
The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).

Related

Extract n-character substring while ignoring spaces

I need to extract a substring (for instance 22 characters) but I need to ignore spaces when counting the number of characters. For example:
$para = "While still in high school I signed up to participate in amateur night at the Educational Alliance. I wanted to show my mother I had talent.";
Let's say I need to get the substring that contains the 22 first characters but without counting the spaces. substr doesn't work:
echo substr($para, 0, 22); // => While still in high sc
But I need to get
// => While still in high school
How can I do this?
^(?=((?>.*?\S){20}))
Try this.Grab the capture or group.See demo.
https://regex101.com/r/fM9lY3/42
This uses lookahead to capture 20 groups of any character and a non space character. Precisely,lookahead will search for groups ending with non space character.Because it is non greedy,it will search first such 20 groups.
you just need to provide a string and length you want to be extracted from that string and function will return that string of specified length(yes return string will have spaces in it, but spaces won't be included in string).
Here is snippet.
$para = "While still in high school I signed up to participate in amateur night at the Educational Alliance. I wanted to show my mother I had talent.";
function getString($str, $length){
$newStr = "";
$counter = 0;
$r = array();
for($i=0; $i<strlen($str); $i++)
$r[$i] = $str[$i];
foreach($r as $char){
$newStr .= $char;
if($char != " "){
$counter += 1;
}
//return string if length reached.
if($counter == $length){
return $newStr;
}
}
return $newStr;
}
echo getString($para, 20);
//output: While still in high scho
echo getString($para, 22);
//output: While still in high school
First, use str_replace() to create a string $parawithoutspaces that consists of $para, without the spaces, like so:
$parawithoutspaces=str_replace(" ", "", $para);
Then, use substr() get the first 20 characters of $parawithoutspaces like so:
print substr($parawithoutspaces, 0, 20);
Or, combining the two steps into one and eliminating the need for the intermediate variable $parawithoutspaces:
print substr(str_replace(" ", "", $para),0,20);
You can try this, it is my code, $result is final string you want :
$arr1 = substr( $string,0,20);
$arr1 = explode(" ",$arr1);
array_pop($arr1);
$result = implode(" ",$arr1);

str replace - replace the x-value

Assuming I have a string
$str="0000,1023,1024,1025,1024,1023,1027,1025,1024,1025,0000";
there are three 1024, I want to replace the third with JJJJ, like this :
output :
0000,1023,1024,1025,1024,1023,1027,1025,JJJJ,1025,0000
how to make str_replace can do it
thanks for the help
As your question asks, you want to use str_replace to do this. It's probably not the best option, but here's what you do using that function. Assuming you have no other instances of "JJJJ" throughout the string, you could do this:
$str = "0000,1023,1024,1025,1024,1023,1027,1025,1024,1025,0000";
$str = str_replace('1024','JJJJ',$str,3)
$str = str_replace('JJJJ','1024',$str,2);
Here is what I would do and it should work regardless of values in $str:
function replace_str($str,$search,$replace,$num) {
$pieces = explode(',',$str);
$counter = 0;
foreach($pieces as $key=>$val) {
if($val == $search) {
$counter++;
if($counter == $num) {
$pieces[$key] = $replace;
}
}
}
return implode(',',$pieces);
}
$str="0000,1023,1024,1025,1024,1023,1027,1025,1024,1025,0000";
echo replace_str($str, '1024', 'JJJJ', 3);
I think this is what you are asking in your comment:
function replace_element($str,$search,$replace,$num) {
$num = $num - 1;
$pieces = explode(',',$str);
if($pieces[$num] == $search) {
$pieces[$num] = $replace;
}
return implode(',',$pieces);
}
$str="0000,1023,1024,1025,1024,1023,1027,1025,1024,1025,0000";
echo replace_element($str,'1024','JJJJ',9);
strpos has an offset, detailed here: http://php.net/manual/en/function.strrpos.php
So you want to do the following:
1) strpos with 1024, keep the offset
2) strpos with 1024 starting at offset+1, keep newoffset
3) strpos with 1024 starting at newoffset+1, keep thirdoffset
4) finally, we can use substr to do the replacement - get the string leading up to the third instance of 1024, concatenate it to what you want to replace it with, then get the substr of the rest of the string afterwards and concatenate it to that. http://www.php.net/manual/en/function.substr.php
You can either use strpos() three times to get the position of the third 1024 in your string and then replace it, or you could write a regex to use with preg_replace() that matches the third 1024.
if you want to find the last occurence of your string you can used strrpos
Do it like this:
$newstring = substr_replace($str,'JJJJ', strrpos($str, '1024'), strlen('1024') );
See working demo
Here's a solution with less calls to one and the same function and without having to explode, iterate over the array and implode again.
// replace the first three occurrences
$replaced = str_replace('1024', 'JJJJ', $str, 3);
// now replace the firs two, which you wanted to keep
$final = str_replace('JJJJ', '1024', $replaced, 2);

Get the current + the next word in a string

this is what I try to get:
My longest text to test When I search for e.g. My I should get My longest
I tried it with this function to get first the complete length of the input and then I search for the ' ' to cut it.
$length = strripos($text, $input) + strlen($input)+2;
$stringpos = strripos($text, ' ', $length);
$newstring = substr($text, 0, strpos($text, ' ', $length));
But this only works first time and then it cuts after the current input, means
My lon is My longest and not My longest text.
How I must change this to get the right result, always getting the next word. Maybe I need a break, but I cannot find the right solution.
UPDATE
Here is my workaround till I find a better solution. As I said working with array functions does not work, since part words should work. So I extended my previous idea a bit. Basic idea is to differ between first time and the next. I improved the code a bit.
function get_title($input, $text) {
$length = strripos($text, $input) + strlen($input);
$stringpos = stripos($text, ' ', $length);
// Find next ' '
$stringpos2 = stripos($text, ' ', $stringpos+1);
if (!$stringpos) {
$newstring = $text;
} else if ($stringpos2) {
$newstring = substr($text, 0, $stringpos2);
} }
Not pretty, but hey it seems to work ^^. Anyway maybe someone of you have a better solution.
You can try using explode
$string = explode(" ", "My longest text to test");
$key = array_search("My", $string);
echo $string[$key] , " " , $string[$key + 1] ;
You can take i to the next level using case insensitive with preg_match_all
$string = "My longest text to test in my school that is very close to mY village" ;
var_dump(__search("My",$string));
Output
array
0 => string 'My longest' (length=10)
1 => string 'my school' (length=9)
2 => string 'mY village' (length=10)
Function used
function __search($search,$string)
{
$result = array();
preg_match_all('/' . preg_quote($search) . '\s+\w+/i', $string, $result);
return $result[0];
}
There are simpler ways to do that. String functions are useful if you don't want to look for something specific, but cut out a pre-defined length of something. Else use a regular expression:
preg_match('/My\s+\w+/', $string, $result);
print $result[0];
Here the My looks for the literal first word. And \s+ for some spaces. While \w+ matches word characters.
This adds some new syntax to learn. But less brittle than workarounds and lengthier string function code to accomplish the same.
An easy method would be to split it on whitespace and grab the current array index plus the next one:
// Word to search for:
$findme = "text";
// Using preg_split() to split on any amount of whitespace
// lowercasing the words, to make the search case-insensitive
$words = preg_split('/\s+/', "My longest text to test");
// Find the word in the array with array_search()
// calling strtolower() with array_map() to search case-insensitively
$idx = array_search(strtolower($findme), array_map('strtolower', $words));
if ($idx !== FALSE) {
// If found, print the word and the following word from the array
// as long as the following one exists.
echo $words[$idx];
if (isset($words[$idx + 1])) {
echo " " . $words[$idx + 1];
}
}
// Prints:
// "text to"

Replace multiple occurrences of a string with different values

I have a script that generates content containing certain tokens, and I need to replace each occurrence of a token, with different content resulting from a separate loop.
It's simple to use str_replace to replace all occurrences of the token with the same content, but I need to replace each occurrence with the next result of the loop.
I did see this answer: Search and replace multiple values with multiple/different values in PHP5?
however it is working from pre-defined arrays, which I don't have.
Sample content:
This is an example of %%token%% that might contain multiple instances of a particular
%%token%%, that need to each be replaced with a different piece of %%token%% generated
elsewhere.
I need to replace each occurrence of %%token%% with content generated, for argument's sake, by this simple loop:
for($i=0;$i<3;$i++){
$token = rand(100,10000);
}
So replace each %%token%% with a different random number value $token.
Is this something simple that I'm just not seeing?
Thanks!
I don't think you can do this using any of the search and replace functions, so you'll have to code up the replace yourself.
It looks to me like this problem works well with explode(). So, using the example token generator you provided, the solution looks like this:
$shrapnel = explode('%%token%%', $str);
$newStr = '';
for ($i = 0; $i < count($shrapnel); ++$i) {
// The last piece of the string has no token after it, so we special-case it
if ($i == count($shrapnel) - 1)
$newStr .= $shrapnel[$i];
else
$newStr .= $shrapnel[$i] . rand(100,10000);
}
I know this is an old thread, but I stumbled across it while trying to achieve something similar. If anyone else sees this, I think this is a little nicer:
Create some sample text:
$text="This is an example of %%token%% that might contain multiple instances of a particular
%%token%%, that need to each be replaced with a different piece of %%token%% generated
elsewhere.";
Find the search string with regex:
$new_text = preg_replace_callback("|%%token%%|", "_rand_preg_call", $text);
Define a callback function to change the matches
function _rand_preg_call($matches){
return rand(100,10000);
}
Echo the results:
echo $new_text;
So as a function set:
function _preg_replace_rand($text,$pattern){
return preg_replace_callback("|$pattern|", "_rand_preg_call", $text);
}
function _rand_preg_call($matches){
return rand(100,10000);
}
I had a similar issue where I had a file that I needed to read. It had multiple occurrences of a token, and I needed to replace each occurrence with a different value from an array.
This function will replace each occurrence of the "token"/"needle" found in the "haystack" and will replace it with a value from an indexed array.
function mostr_replace($needle, $haystack, $replacementArray, $needle_position = 0, $offset = 0)
{
$counter = 0;
while (substr_count($haystack, $needle)) {
$needle_position = strpos($haystack, $needle, $offset);
if ($needle_position + strlen($needle) > strlen($haystack)) {
break;
}
$haystack = substr_replace($haystack, $replacementArray[$counter], $needle_position, strlen($needle));
$offset = $needle_position + strlen($needle);
$counter++;
}
return $haystack;
}
By the way, 'mostr_replace' is short for "Multiple Occurrence String Replace".
You can use the following code:
$content = "This is an example of %%token%% that might contain multiple instances of a particular %%token%%, that need to each be replaced with a different piece of %%token%% generated elsewhere.";
while (true)
{
$needle = "%%token%%";
$pos = strpos($content, $needle);
$token = rand(100, 10000);
if ($pos === false)
{
break;
}
else
{
$content = substr($content, 0,
$pos).$token.substr($content, $pos + strlen($token) + 1);
}
}

Increment integer at end of string

I have a string, "Chicago-Illinos1" and I want to add one to the end of it, so it would be "Chicago-Illinos2".
Note: it could also be Chicago-Illinos10 and I want it to go to Chicago-Illinos11 so I can't do substr.
Any suggested solutions?
Complex solutions for a really simple problem...
$str = 'Chicago-Illinos1';
echo $str++; //Chicago-Illinos2
If the string ends with a number, it will increment the number (eg: 'abc123'++ = 'abc124').
If the string ends with a letter, the letter will be incremeted (eg: '123abc'++ = '123abd')
Try this
preg_match("/(.*?)(\d+)$/","Chicago-Illinos1",$matches);
$newstring = $matches[1].($matches[2]+1);
(can't try it now but it should work)
$string = 'Chicago-Illinois1';
preg_match('/^([^\d]+)([\d]*?)$/', $string, $match);
$string = $match[1];
$number = $match[2] + 1;
$string .= $number;
Tested, works.
explode could do the job aswell
<?php
$str="Chicago-Illinos1"; //our original string
$temp=explode("Chicago-Illinos",$str); //making an array of it
$str="Chicago-Illinos".($temp[1]+1); //the text and the number+1
?>
I would use a regular expression to get the number at the end of a string (for Java it would be [0-9]+$), increase it (int number = Integer.parse(yourNumberAsString) + 1), and concatenate with Chicago-Illinos (the rest not matched by the regular expression used for finding the number).
You can use preg_match to accomplish this:
$name = 'Chicago-Illinos10';
preg_match('/(.*?)(\d+)$/', $name, $match);
$base = $match[1];
$num = $match[2]+1;
print $base.$num;
The following will output:
Chicago-Illinos11
However, if it's possible, I'd suggest placing another delimiting character between the text and number. For example, if you placed a pipe, you could simply do an explode and grab the second part of the array. It would be much simpler.
$name = 'Chicago-Illinos|1';
$parts = explode('|', $name);
print $parts[0].($parts[1]+1);
If string length is a concern (thus the misspelling of Illinois), you could switch to the state abbreviations. (i.e. Chicago-IL|1)
$str = 'Chicago-Illinos1';
echo ++$str;
http://php.net/manual/en/language.operators.increment.php

Categories