I have a little problem in PHP.
$string = "[:string] has [:int] [:string] and [:int] [:string]";
I just wanna modify (probably with str_replace) it with:
$string = "He has 5 apples and 3 bananas";
How could I do that?
(Classic str_replace() will modify all [:int] with the same word,
and is not what I want).
Thank you very much...
You could use the following regex, to capture all groups to replace and then iterate over it.
\[:([^\]]+)\]
Or you can just use preg_replace_callback and pass an desired replace function to it.
$data = [...];
preg_replace_callback('/\[:([^\]]+)\]/', $str, function (&$matches) use ($data) {
return doSomethingWithMatches..
});
Related
I know that the answer is probably simple and I am just not seeing it.
This code gets me an array of "tags" in the layout (eg [[tag]]), and I have an array of replacements that comes in with the request ($this->data). My first inclination was to use preg_match_all to get an array of all the tags and just pass in both arrays:
if(isset($this->layout))
{
ob_start();
include(VIEWS.'layouts/'.$this->layout.'.phtml');
$this->layout = ob_get_contents();
preg_match_all('/\[\[.*\]\]/', $this->layout, $tags);
print preg_replace($tags, $this->data, $this->layout);
}
But the arrays are not the same length (most of the time). The layout might reuse some tags, and the passed in data variables might not include some tags in the layout.
I feel like there must be a more efficient way to do this than doing a foreach and building the output in iterations.
This project is way too small to implement a full templating engine like Smarty or Twig... it is actually just a few pages and a few replacements. My client just wants a simple way to add things like page titles and email recipients, etc.
Any advice would be appreciated. Like I said, I am positive that it is something simple that I am overlooking.
EDIT:
$this->data is an array of replacement text that look like:
tag => replacement_text
EDIT 2:
If I user preg_match_all('/\[\[(.*)\]\]/', $this->layout, $tags); the array includes JUST the tags (no [[]]), I just need a way to match them up with the array of replacement strings in $this->data.
You can simply use str_replace for this job, creating an array of search strings and replacements from $this->data:
$search = array_map(function ($s) { return "[[$s]]"; }, array_keys($this->data));
$replacements = array_values($this->data);
echo str_replace($search, $replacements, $this->layout);
Demo on 3v4l.org
You don't need to get $tags by matching $this->layout, the information is all in the keys of $this->data. You just need to add [[...]] around the keys.
$tags = array_map(function($key) {
return '/\[\[' . preg_quote($key) . '\]\]';
}, array_keys($this->data));
Another solution is to use preg_replace_callback() to look the tag up in $this->data;
echo preg_replace_callback('/\[\[(.*?)\]\]/', function($matches) {
return $this->data[$matches[1]] ?? $matches[0];
}, $this->layout);
Note that I changed the regexp to use a non-greedy quantifier; your regexp will match from the beginning of the first tag to the end of the last tag.
If the tag isn't found in $this->data, ?? $matches[0] leaves it unchanged.
You could make use of preg_replace_callback:
$result = preg_replace_callback('/\[\[(?<tag>.*?)]]/', function ($matches) {
return $this->data[$matches['tag']] ?? $matches[0];
}, $this->layout);
Demo: https://3v4l.org/I9Vvh
Shorter PHP 7.4 version:
$result = preg_replace_callback('/\[\[(?<tag>.*?)]]/', fn($matches) =>
$this->data[$matches['tag']] ?? $matches[0], $this->layout);
Edited with the ?? $matches[0] (courtesy of #Barmar) -- this is basically the same answer, just leaving it in case the PHP 7.4 syntax is useful.
I am trying to replace word or sequence of words in a string using preg_replace?
For example:
Change These:
ABCExample to abcExample
AnotherExample to anotherExample
XyzAbcExample to xyzAbcExample
Leave as it is:
xyzExample to xyzExample
new to new
You need to use preg_replace_callback function.
$str = <<<EOT
ABCExample
AnotherExample
XyzAbcExample
xyzExample
new
EOT;
echo preg_replace_callback('~(?m)^[A-Za-z]*?(?=(?:[A-Z][a-z]+)+$)~', function ($m)
{
return strtolower($m[0]);
}, $str);
I guess you are looking for str_ireplace.
This function returns a string or an array with all occurrences of
search in subject (ignoring case) replaced with the given replace
value. If you don't need fancy replacing rules, you should generally
use this function instead of preg_replace() with the i modifier.
Sample code (and a sample program):
$res1 = str_ireplace("abc", "xyz", "ABCExample to abcExample");
echo $res1;
Output: xyzExample to xyzExample
$text = "
<tag>
<html>
HTML
</html>
</tag>
";
I want to replace all the text present inside the tags with htmlspecialchars(). I tried this:
$regex = '/<tag>(.*?)<\/tag>/s';
$code = preg_replace($regex,htmlspecialchars($regex),$text);
But it doesn't work.
I am getting the output as htmlspecialchars of the regex pattern. I want to replace it with htmlspecialchars of the data matching with the regex pattern.
what should i do?
You're replacing the match with the pattern itself, you're not using the back-references and the e-flag, but in this case, preg_replace_callback would be the way to go:
$code = preg_replace_callback($regex,'htmlspecialchars',$text);
This will pass the mathces groups to htmlspecialchars, and use its return value as replacement. The groups might be an array, in which case, you can try either:
function replaceCallback($matches)
{
if (is_array($matches))
{
$matches = implode ('', array_slice($matches, 1));//first element is full string
}
return htmlspecialchars($matches);
}
Or, if your PHP version permits it:
preg_replace_callback($expr, function($matches)
{
$return = '';
for ($i=1, $j = count($matches); $i<$j;$i++)
{//loop like this, skips first index, and allows for any number of groups
$return .= htmlspecialchars($matches[$i]);
}
return $return;
}, $text);
Try any of the above, until you find simething that works... incidentally, if all you want to remove is <tag> and </tag>, why not go for the much faster:
echo htmlspecialchars(str_replace(array('<tag>','</tag>'), '', $text));
That's just keeping it simple, and it'll almost certainly be faster, too.
See the quickest, easiest way in action here
If you want to isolate the actual contents as defined by your pattern, you could use preg_match($regex,$text,$hits);. This will give you an array of hits those bits that were between the paratheses in the pattern, starting at $hits[1], $hits[0] contains the whole matched string). You can then start manipulating these found matches, possibly using htmlspecialchars ... and combine them again into $code.
I have a string of varying length taken from a MySQL database and in that string is a value (in bold below):
s:1:"4", s:2:"53", s:3:"7", s:4:"5"
I need a way to find whatever is in quotes following the s:3:. So in this example, it would be 7. I've looked around and I think I need to use the explode function but I am having trouble implementing it. The string may contain multiple values of this in which case I'd like to get them all into an array.
Use preg_match_all() for that:
$str = 's:1:"4", s:2:"53", s:3:"7", s:4:"5"';
if(preg_match_all('/s:3:"(.*?)"/', $str, $matches)) {
var_dump($matches[1]);
}
Non-greedy method, includes multi-lines.
<?php
$str = 's:1:"4", s:2:"53", s:3:"7", s:4:"5"';
if(preg_match_all('!s:3:"([^"]+)"!s', $str, $matches)) {
print_r($matches);
}
?>
Please excuse my noob-iness!
I have a $string, and would like to see if it contains any one or more of a group of words, words link ct, fu, sl** ETC. So I was thinking I could do:
if(stristr("$input", "dirtyword1"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord");
}
elseif(stristr("$input", "dirtyWord1"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord2");
}
...ETC. BUT, I don't want to have to keep doing if/elseif/elseif/elseif/elseif...
Can't I just do a switch statement OR have an array, and then simply say something like?:
$dirtywords = { "f***", "c***", w****", "bit**" };
if(stristr("$input", "$dirtywords"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord");
}
I'd appreciate any help at all
Thank you
$dirty = array("fuc...", "pis..", "suc..");
$censored = array("f***", "p***", "s***");
$input= str_ireplace($dirty, $censored , $input);
Note, that you don't have to check stristr() to do a str_ireplace()
http://php.net/manual/en/function.str-ireplace.php
If search and replace are arrays, then str_ireplace() takes a value from each array and uses them to do search and replace on subject. If replace has fewer values than search, then an empty string is used for the rest of replacement values. If search is an array and replace is a string, then this replacement string is used for every value of search.
Surely not the best solution since I don't know too much PHP, but what about a loop ?
foreach (array("word1", "word2") as $word)
{
if(stristr("$input", $word))
{
$input = str_ireplace("$input", $word" "thisWillReplaceDirtyWord");
}
}
When you have several objects to test, think "loop" ;-)