dynamic variables in preg_replace in PHP - php

I have a text template like this:
$template = [FIRSTNAME] say hello to [NAME]
I have an user array like
[user_name] => myname
[user_firstname] => myfirstname
and I would like to transform it with preg_replace so I tried this:
$replacement = '$user[user_${1}]';
$result['texte'] = preg_replace('/[(.*)]/', {$replacement}, $result['texte']);
without any success :(

/[(.*)]/ does not escape the [ or ], and would match essentially everything if it did. Use /\[(.*?)\]/. Additionally, you need to strtolower the matched inner value.
$template = "[FIRSTNAME] say hello to [NAME]";
$replacements = array(
'user_name' => 'myname',
'user_firstname' => 'myfirstname',
);
$result['texte'] = preg_replace_callback('/\[(.*?)\]/', function ($match)
use ($replacements) {
return $replacements["user_" . strtolower($match[1])];
}, $template)

Related

String Replace that contains hashtags-php

I have a string like this
$content="#Love #Lovestories #Lovewalapyar";
Want to make these hashtags clickable.
I have an array.
$tags=
(
[0] => stdClass Object
(
[TOPIC_ID] => 132
[TOPIC_NAME] => Love
[TOPIC_URL] => http://local/topic/132/love
)
[1] => stdClass Object
(
[TOPIC_ID] => 3347
[TOPIC_NAME] => LoveStories
[TOPIC_URL] => http://local/topic/3347/lovestories
)
[2] => stdClass Object
(
[TOPIC_ID] => 43447
[TOPIC_NAME] => lovewalapyar
[TOPIC_URL] => http://local/topic/43447/lovewalapyar
)
);
Using this to make hashtags clickable.
foreach($tags as $tag){
$content=str_ireplace('#'.$tag->TOPIC_NAME, '#'.$tag->TOPIC_NAME.'', $content);
}
Getting this:
It replaces only love not the other string.
Trying to replace/Make these hashtags clickable.
Any help would be much appriciated.
The reason is simple. You have hashtags which are substrings of other hashtags.
To avoid this overlapping issue, you can sort your array in a non-increasing fashion replacing longer strings first and shorter strings later, completely avoid the overlapping issue, like below:
<?php
usort($tags,function($a,$b){
return strlen($b->TOPIC_NAME) <=> strlen($a->TOPIC_NAME);
});
Update:
Your hashtag text inside <a></a> is causing the str_ireplace to reconsider it. For this you need to pass the array values and their respective replacements in an array, or, instead of adding a #, you can use a HTML character entity # which will be ignored by str_ireplace() and would work properly, like below:
'<a ...>#'.$tag->TOPIC_NAME.'</a>';
Updated Snippet:
<?php
usort($tags,function($a,$b){
return strlen($b->TOPIC_NAME) <=> strlen($a->TOPIC_NAME);
});
foreach($tags as $tag){
$content = str_ireplace('#'.$tag->TOPIC_NAME, '#'. $tag->TOPIC_NAME.'', $content);
}
I would use the regular expression /#(\w*)/ (hashtag and whitespace) and preg_replace() to replace all occurrences.
Something like this:
$content = "#Love #Lovestories #Lovewalapyar";
$pattern = '/#(\w*)/';
$replacement = '$1';
preg_replace($pattern, $replacement, $content);
this will give you:
Love
Lovestories
Lovewalapyar
You can test that regex online here.
If you need some advanced logic as Magnus Eriksson mentioned in comments you can use preg_match_all and iterate over your found matches.
Something like this:
$content = "#Love #Lovestories #Lovewalapyar";
$pattern = '/#(\w*)/';
preg_match_all($pattern, $content, $matches);
foreach ($matches[1] as $key => $match) {
// do whatever you need here, you might want to use $tag = $tags[$key];
}

Get matches from a preg_replace and use them as an array key

I want to get matches from a String and use them in a array as key to change the value in the string to the value of the array.
If it would be easier to realize, i can change the fantasy tags from %! also to whatever don't have problems in JS/jQuery. This script is for external JS Files and change some variables, which I can't Access from JS/jQuery. So I want to insert them with PHP and send them minified and compressed to the Browser.
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$string = preg_replace('%!(.*?)!%',$array[$1],$string);
echo $string;
You can use array_map with preg_quote to turn the keys of your array into regexes, and then use the values of the array as replacement strings in the array form of preg_replace:
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$regexes = array_map(function ($k) { return "/" . preg_quote("%!$k!%") . "/"; }, array_keys($array));
$string = preg_replace($regexes, $array, $string);
echo $string;
Output:
This is just a Test String and i wanna Change the Variable
Demo on 3v4l.org

PHP - preg_replace on an array not working as expected

I have a PHP array that looks like this..
Array
(
[0] => post: 746
[1] => post: 2
[2] => post: 84
)
I am trying to remove the post: from each item in the array and return one that looks like this...
Array
(
[0] => 746
[1] => 2
[2] => 84
)
I have attempted to use preg_replace like this...
$array = preg_replace('/^post: *([0-9]+)/', $array );
print_r($array);
But this is not working for me, how should I be doing this?
You've missed the second argument of preg_replace function, which is with what should replace the match, also your regex has small problem, here is the fixed version:
preg_replace('/^post:\s*([0-9]+)$/', '$1', $array );
Demo: https://3v4l.org/64fO6
You don't have a pattern for the replacement, or a empty string place holder.
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject)
Is what you are trying to do (there are other args, but they are optional).
$array = preg_replace('/post: /', '', $array );
Should do it.
<?php
$array=array("post: 746",
"post: 2",
"post: 84");
$array = preg_replace('/^post: /', '', $array );
print_r($array);
?>
Array
(
[0] => 746
[1] => 2
[2] => 84
)
You could do this without using a regex using array_map and substr to check the prefix and return the string without the prefix:
$items = [
"post: 674",
"post: 2",
"post: 84",
];
$result = array_map(function($x){
$prefix = "post: ";
if (substr($x, 0, strlen($prefix)) == $prefix) {
return substr($x, strlen($prefix));
}
return $x;
}, $items);
print_r($result);
Result:
Array
(
[0] => 674
[1] => 2
[2] => 84
)
There are many ways to do this that don't involve regular expressions, which are really not needed for breaking up a simple string like this.
For example:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
$o = explode(': ', $n);
return (int)$o[1];
}, $input);
var_dump($output);
And here's another one that is probably even faster:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
return (int)substr($n, strpos($n, ':')+1);
}, $input);
var_dump($output);
If you don't need integers in the output just remove the cast to int.
Or just use str_replace, which in many cases like this is a drop in replacement for preg_replace.
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = str_replace('post: ', '', $input);
var_dump($output);
You can use array_map() to iterate the array then strip out any non-digital characters via filter_var() with FILTER_SANITIZE_NUMBER_INT or trim() with a "character mask" containing the six undesired characters.
You can also let preg_replace() do the iterating for you. Using preg_replace() offers the most brief syntax, but regular expressions are often slower than non-preg_ techniques and it may be overkill for your seemingly simple task.
Codes: (Demo)
$array = ["post: 746", "post: 2", "post: 84"];
// remove all non-integer characters
var_export(array_map(function($v){return filter_var($v, FILTER_SANITIZE_NUMBER_INT);}, $array));
// only necessary if you have elements with non-"post: " AND non-integer substrings
var_export(preg_replace('~^post: ~', '', $array));
// I shuffled the character mask to prove order doesn't matter
var_export(array_map(function($v){return trim($v, ': opst');}, $array));
Output: (from each technique is the same)
array (
0 => '746',
1 => '2',
2 => '84',
)
p.s. If anyone is going to entertain the idea of using explode() to create an array of each element then store the second element of the array as the new desired string (and I wouldn't go to such trouble) be sure to:
split on or : (colon, space) or even post: (post, colon, space) because splitting on : (colon only) forces you to tidy up the second element's leading space and
use explode()'s 3rd parameter (limit) and set it to 2 because logically, you don't need more than two elements

php string with special character to array

I have a PHP variable called $array, which will output something like
"...", "...", "...", "...", ... when echo'd
but ... may content some character like " , , and spaces or may even contain ", "
How can I change it to an array like Array([0] => ... [1] => ... [2] => ... [3] => ... etc)?
PHP explode
$array = explode(",",$array); // split the string into an array([0] => '"..."', etc)
foreach ($array as $entry) {
// clean up the strings as needed
}
You can use the str_replace function :
$str = "....'...,,,";
$unwantedChars = array("'", ",");
$cleanString = str_replace($unwantedChars, "",$str);
echo $cleanString;
You can add as many characters in the unwantedChar array you want

BBCode only use the first replacement but not the others

The code below will only use the first line in the array (which makes the text bold).
function bbcode($string) {
$codes = Array(
'/\[b\](.+?)\[\/b\]/' => '<b>\1</b>',
'/\[i\](.+?)\[\/i\]/' => '<i>\1</i>',
'/\[u\](.+?)\[\/u\]/' => '<u>\1</u>',
'/\[s\](.+?)\[\/s\]/' => '<s>\1</s>',
'/\[url=(.+?)\](.+?)\[\/url\]/' => '\2',
'/\[image=(.+?)\]/' => '<div class="centered"><img src="\1" alt=""></div>'
);
while($replace = current($codes)) {
$bbcode = preg_replace(key($codes), $replace, $string);
next($codes);
return stripslashes(nl2br($bbcode));
}
}
echo bbcode('[b]This text[/b] will be bold and also [b]this text[/b]. But when I use some other BBCodes, it will [u]not[/u] work as planned. Here's a [url=http://google.com/]link[/url] too which will not be replaced as planned.');
Output: This text will be bold and also this text. But when I use some other bbcode, it will [u]not[/u] work as planned. Here's a [url=http://google.com/]link[/url] too which will not be replaced as planned.
How can I do so that my code will search for the right BBCode in the array and replace it with the key?
preg_replace accepts arrays as well for patterns and replacements.
Use the notation $n in the replacement part instead of \n that is reserved for the pattern.
Here is what I'd do:
function bbcode($string) {
$codes = Array(
'/\[b\](.+?)\[\/b\]/' => '<b>$1</b>',
'/\[i\](.+?)\[\/i\]/' => '<i>$1</i>',
'/\[u\](.+?)\[\/u\]/' => '<u>$1</u>',
'/\[s\](.+?)\[\/s\]/' => '<s>$1</s>',
'/\[url=(.+?)\](.+?)\[\/url\]/' => '$2',
'/\[image=(.+?)\]/' => '<div class="centered"><img src="$1" alt=""></div>'
);
$bbcode = preg_replace(array_keys($codes), array_values($codes), $string);
return stripslashes(nl2br($bbcode));
}

Categories