Replace multiple substrings in PHP without going over old ones - php

When trying to use PHP's str_replace function to replace multiple substrings, is there a way to get it to ignore the strings it's just replaced?
For example, when executing the following code block, it replaces the "o" in "<strong>" from the first replacement.
$str="Hello world.";
$old=array("e","o");
$new=array("<strong>e</strong>","<strong>o</strong>");
echo str_replace($old,$new,$str);
The actual output:
// "H<str<strong>o</strong>ng>e</str<strong>o</strong>ng>ll<strong>o</strong> w<strong>o</strong>rld."
The expected output:
// "H<strong>e</strong>ll<strong>o</strong> w<strong>o</strong>rld."

Use strtr().
From the PHP manual:
The longest keys will be tried first. Once a substring has been replaced, its new value will not be searched again.

The alternative solution using preg_replace function:
echo preg_replace("/(e|o)/i", "<strong>$1</strong>", $str);
// H<strong>e</strong>ll<strong>o</strong> w<strong>o</strong>rld.

Related

How to extract substring between two substrings from a string in php?

For example:
$string="<aa>xyz<bb>123<ccc>";
I want to get the substring 'xyz' from $string.Is it possible?
Simply you can use strip_tags to get xyz
<?php
echo strip_tags('<aa>xyz<bb>');
?>
strip_tags is only striping tags. Use it only if this meets your requirement.
You can also use a regex to explode the string into an array. this would give you the substring you want in $arr[0]
This will work regardless what the tags are, and allow you to easily which ever substring you want.
<?php
$string="<aa>xyz<bb>123<ccc>";
$arr = preg_split("/<[^>]+>/", $string, 0, PREG_SPLIT_NO_EMPTY);
var_export($arr);
yes it is possible
$string="<aa>xyz<bb>";
echo substr($string,4,4);
you can also do this by strip_tags() it Strip HTML and PHP tags from a string
Use preg_match with <aa>(.*?)</bb> , it will be the first match.
With regular expressions you will also be able to get other matches in your string also ..

PHP escaping delimiter

I am using PHPs' strtr method to replace certain tokens/placeholders in a string. This works very well but now I'm trying to work out if all of my tokens were replaced.
The following example:
$trans = array(":hello" => "hi", ":hi" => "hello");
echo strtr(":hi all, I said :hello", $trans);
will output:
hello all, I said hi
Both tokens were replaced successfully but how do I check this. I can't search the output for occurrences of my delimiter ':' since the output string could contain valid ':' in the data.
Is there a way that I can escape these delimiters before doing the replace, then do a count on the unescaped delimiters to see if there were any token left unreplaced, and then finally unescape the escaped delimiters before returning?
NOTE: I cannot use str_replace, this method needs to be used.
I don't think strtr can help you here, it just replaces whatever it finds. What you seem to want is to figure out if there is a difference between the tokens in the array and in the string. For that, something like this should do:
preg_match_all('/:\w+/', $str, $matches);
if (array_diff($matches[0], array_keys($trans))) {
// the string has tokens that aren't in $trans
}

Replace array values in string with regex?

Say I have the following array and string:
$array = array('$AA', '$AB', '$AC', '$ZZ');
$string = 'String mentioning $AA and $AB and $CZ and $MARTASS';
I want to check $string for matches against $array. Every word in $string that begins with "$" should be checked. In the example, a match is found for $AA and $AB; not for $CZ. The desired output would be:
String mentioning {MATCH} and {MATCH} and {NO-MATCH}
Is this possible with one regex or is it better to write several lines of PHP? Any input is kindly received :)
Should be possible with two find-and-replaces, done in this order:
first:
\b(($AA)|($AB)|($AC)|($ZZ))\b ---> {MATCH}
second:
\b$\w+\b ---> {NO-MATCH}
I'm not sure this is in PHP syntax, but it shouldn't be too hard to get there. \b is a word separator boundary, which I believe is allowed in PHP.
Edit: You might need to escape $, not sure as it's grouped.
Yes it is possible. Have a look at the examples in the preg_replace_callback() documentation. You would use a replace call of the form:
function substituteVar($matches) {
...
}
...
$newString = preg_replace_callback("/\\$(\w+)/", 'substituteVar', $string);
I think I'll leave the content of the substituteVar() as an "exercise for the reader". :-)
This should work...
<?php
$string = 'String mentioning $AA and $AB and $CZ and $MARTASS';
echo preg_replace_callback("/\\$\S+/",
create_function('$a','return in_array($a[0],array("\$AA", "\$AB", "\$AC", "\$ZZ")) ? "{MATCH}" : "{NO-MATCH}";'),
$string
);
?>
Regex matches $ followed by one or more not spaces (\S+) and then checks if the matched string is in the array (included in create function definition so it is in scope, and escaped properly)
I wouldn't bother using a regex here, a simple scan of the string from start to finish, looking for the '$' character and then performing a binary search on the array would be much simpler and faster.

How to use preg_replace in php to replace text with function result?

I have a complicated problem:
I have a very long text and I need to call some php functions inside my text.
The function name is myfunction();
I`we included in my text the function in the following way:
" text text text myfunction[1,2,3,4,5]; more text text ... "
And I want to replace each myfunction[...] with the result of the function myfunction with the variables from the [] brackets.
my code is:
<?php echo preg_replace('/myfunction[[0-9,]+]/i',myfunction($1),$post['content']); ?>
,but it`s not working.
The parameter should be an array, because it can contain any number of values.
If I were you, I would avoid using the e modifier to preg_replace because it can lead you open to execution of arbitrary code. Use preg_replace_callback instead. It's slightly more verbose, but much more effective:
echo preg_replace_callback('/myfunction\[([0-9,]+)\]/i', function($matches) {
$args = explode(',', $matches[1]); // separate the arguments
return call_user_func_array('myfunction', $args); // pass the arguments to myfunction
}, $post['content']);
This uses an anonymous function. This functionality won't be available to you if you use a version of PHP before 5.3. You'll have to create a named function and use that instead, as per the instructions on the manual page.
You can use preg_replace()'s "e" modifier (for EVAL) used like this :
$text = preg_replace('/myfunction\[(.*?)\]/e', 'myfunction("$1")', $text);
I didn't really get how your data is structured so it's all I can do to help you at the moment. You can explore that solution.
From the PHP Manual :
e (PREG_REPLACE_EVAL)
If this modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evaluates it as PHP code, and uses the result for replacing the search string. Single quotes, double quotes, backslashes () and NULL chars will be escaped by backslashes in substituted backreferences.
You need to add the "e" modifier, escape [ and ] in the regex expression and stringify the second argument.
preg_replace('/myfunction\[[0-9,]+\]/ei','myfunction("$1")',$post['content']);

preg_replace on the matches of another preg_replace

I have a feeling that I might be missing something very basic. Anyways heres the scenario:
I'm using preg_replace to convert ===inputA===inputB=== to inputA
This is what I'm using
$new = preg_replace('/===(.*?)===(.*?)===/', '$1', $old);
Its working fine alright, but I also need to further restrict inputB so its like this
preg_replace('/[^\w]/', '', every Link or inputB);
So basically, in the first code, where you see $2 over there I need to perform operations on that $2 so that it only contains \w as you can see in the second code. So the final result should be like this:
Convert ===The link===link's page=== to The link
I have no idea how to do this, what should I do?
Although there already is an accepted answer: this is what the /e modifier or preg_replace_callback() are for:
echo preg_replace(
'/===(.*?)===(.*?)===/e',
'"$1"',
'===inputA===in^^putB===');
//Output: inputA
Or:
function _my_url_func($vars){
return ''.$vars[2].'';
}
echo preg_replace_callback(
'/===(.*?)===(.*?)===/',
'_my_url_func',
'===inputA===inputB===');
//Output: inputB
Try preg_match on the first one to get the 2 matches into variables, and then use preg_replace() on the one you want further checks on?
Why don't you do extract the matches from the first regex (preg_match) and treat thoses results and then put them back in a HTML form ?

Categories