This question already has answers here:
calling function inside preg_replace thats inside a function
(2 answers)
Closed 8 years ago.
I'm trying to come up with a way to find all RegEx matches in a string, then run all of those matches through a function that I've written, but I'm having no luck.
Specifically, I'm trying to find all email addresses in a string and then use a function to convert those addresses into useful mailto links that hide the addresses from spam bots.
So I start with plain old RegEx to turn the addresses into mailto links, just so I know that the matches are working.
$pattern = '#([0-9a-z]([-_.]?[0-9a-z])*#[0-9a-z]([-.]?[0-9a-z])*\\.[a-wyz][a-z](fo|g|l|m|mes|o|op|pa|ro|seum|t|u|v|z)?)#i';
$replacement = "<a href='mailto:\\1'>\\1</a>";
$description = preg_replace($pattern, $replacement, $description);
Works great. So far, so good. But when I try to use my function to manipulate the address string, email addresses are no longer matched.
$pattern = '#([0-9a-z]([-_.]?[0-9a-z])*#[0-9a-z]([-.]?[0-9a-z])*\\.[a-wyz][a-z](fo|g|l|m|mes|o|op|pa|ro|seum|t|u|v|z)?)#i';
$replacement = myFunction('\\1');
$description = preg_replace($pattern, $replacement, $description);
What am I doing wrong?
$description = preg_replace_callback($pattern, 'myFunction', $description);
Check preg_replace_callback() on manual to understand how it works.
Your myFunction() function should be coded like that:
function myFunction($matches)
{
return sprintf('%s', $matches[1], $matches[1]);
}
Using preg_replace_callback() with a closure (PHP 5.3+):
$description = preg_replace_callback($pattern, function ($matches) {
return myFunction($matches[1]);
}, $description);
Related
This question already has answers here:
how to extract links and titles from a .html page?
(6 answers)
Closed 3 years ago.
Hi know there's already a lot of question about this so far. But I've tried a lot of them and can't get it quite where I need it.
I need a regex that will extract a youtube url from a string that contains an iframe.
Sample text:
<p>
</p><p>Garbage text</p><p><iframe width="560" height="315" src="//www.youtube.com/embed/PZlJFGgFTfA" frameborder="0" allowfullscreen=""></iframe></p>
Here's the regex I come up with :
(\bhttps?:)?\/\/[^,\s()<>]+(?:\([\w\d]+\)|(?:[^,[:punct:]\s]|\/))
Regex101 test
I'm using it on a function and it returned an empty array. Do someone have an idea what's wrong with my function ?
function extractEmbedYT($str) {
preg_match('/(\bhttps?:)?\/\/[^,\s()<>]+(?:\([\w\d]+\)|(?:[^,[:punct:]\s]|\/))/', $str, $matches, PREG_OFFSET_CAPTURE, 0);
return $matches;
}
EDIT 1 : Changed capture group in my regex so it don't capture last the last char
EDIT 2 : Added some PHP Code to put in context, since it's working in Regex101 but not on my script.
You need to convert the capturing group to a non-capturing one:
/(\bhttps?:)?\/\/[^,\s()<>]+(?:\(\w+\)|(?:[^,[:punct:]\s]|\/))/s
^^^
Also, in the code, you need to pass $string to the function, not $str:
function stripEmptyTags ($result)
{
$regexps = array (
'~<(\w+)\b[^\>]*>([\s]| )*</\\1>~',
'~<\w+\s*/>~',
);
do
{
$string = $result;
$result = preg_replace ($regexps, '', $string);
}
while ($result != $string);
return $result;
}
function extractEmbedYT($str) {
// Find all URLS in $str
preg_match_all('/(\bhttps?:)?\/\/[^,\s()<>]+(?:\(\w+\)|(?:[^,[:punct:]\s]|\/))/s', $str, $matches);
// Remove all iframes from $str
$str = preg_replace('/<iframe.*?<\/iframe>/i','', $str);
$str = stripEmptyTags($str);
return [$str, $matches[0]];
}
$string = '<p>
</p><p>UDA Stagiaire</p><p><iframe width="560" height="315" src="//www.youtube.com/embed/PZlJFGgFTfA" frameborder="0" allowfullscreen=""></iframe></p>';
$results = extractEmbedYT($string);
print_r($results);
See the online PHP demo.
I know this question has more of a WordPress background to it, but I'm hoping it's just my lack of PHP knowledge that is the problem here.
I have a regex that looks for <a> tags such as: Find Out More, which are generated from content inputted by the user. Once it finds this content a foreach loop runs over the matched text and uses a WordPress function $postId = url_to_postid( $url ); to convert the URL into a PostID.
This is an example output: Find Out More.
This works fine as long as there is one link in each piece of matched text. However if there are two or more links, it sets every link to have the same href which is incorrect.
I'm sure this is something to do with how I've got my loop running. The code I'm using is below:
<?php
$string = get_field('sample_text_box');
$pattern = "/(?<=href=(\"|'))[^\"']+(?=(\"|'))/";
preg_match_all($pattern, $string, $matches);
$urls = $matches[0];
foreach($urls as $key => $url) {
$postId[$key] = url_to_postid( $url );
}
$newstring = preg_replace($pattern , $postId[$key] , $string);
echo $newstring;
?>
The line get_field('sample_text_box'); is an Advanced Custom Field function which "returns the value of the specified field". You can read about it here if it helps: https://www.advancedcustomfields.com/resources/get_field/
Thanks!
The problem with your code is that you are indeed replacing the pattern with a single value of $postId[$key], where $key is the last value assigned in foreach.
You also can not pass $postId instead because preg_replace expects both pattern and replacement be of the same type - whether strings, or arrays.
However, the problem is easily solved with preg_replace_callback function:
$pattern = '/(?<=href\="|\')([^"\']+)(?="|\')/m';
$new_string = preg_replace_callback($pattern, function ($matches) {
return isset($matches[1]) ? url_to_postid($matches[1]) : $matches[0];
}, $string);
I want to replace a section of a string based that starts with one string and ends with another, and I want the section between also replaced. I think this is possible using regex but I cant' seem to find any decent examples showing this.
For Example:
I have "http://www.website.com" and I want to replace from "www" to "com" with "123xyz".
So"http://www.website.com/something" becomes "http://123xyz/something.
I am assuming I have to use preg_replace(), and I think the regex should start with "^www" and end with "com$", but I cant seem to get a grasp of the syntax of regex enough to create the desired effect.
please help
With reference to your example , you can try like this
$string = 'http://www.website.com/something';
$pattern = '/www(.*)com/';
$replacement = '123xyz';
echo preg_replace($pattern, $replacement, $string);
$phrase = "http://www.website.com";
$phraseWords = array("www", "com");
$replaceTo = array("123xyz", "something");
$result = str_replace($phraseWords, $replaceTo, $phrase);
echo $result;
Thanks so much to both #CodingAnt and #PHPWeblineindia for your great answers. Using #CodingAnt's answer (and some more research I did online) I wrote this function:
function replaceBetween(&$target, $from, $to, $with){
if(strpos($target, $from)===false)return false;
$regex = "'".$from."(.*?)".$to."'si";
preg_match_all($regex, $target, $match);
$match = $match[1];
foreach($match as $m) $target = str_replace($from.$m.$to, $with, $target);
return $target;
}
It seems to work pretty well. I hope someone finds this useful.
I need some special filtering to certain text all over my website, like below:
function special_text( $content ) {
$search_for = 'specialtext';
$replace_with = '<span class="special-text"><strong>special</strong>text</span>';
return str_replace( $search_for, $replace_with, $content );
}
add_filter('the_content', 'special_text', 99);
It's doing thing in an excellent way, BUT...
in content if there's any link like: <a title="specialtext" href="http://specialtext.com">specialtext</a> then the title and href texts also changed and the link becomes broken.
How can I make exception there?
Is there a way I can put some exceptions in an array and str_replace() simply skip 'em?
You should use regular expression and use function preg_replace() to replace matched string. Here is the full implementation of your special_text() function.
function special_text( $content ) {
$search_for = 'specialtext';
$replace_with = '<span class="special-text"><strong>special</strong>text</span>';
return preg_replace( '/<a.*?>(*SKIP)(*F)|'.$search_for.'/m', $replace_with, $content );
}
In the following regular expression first, using <a.*?> - everything between <a...> is matched and using (*SKIP)(*F)| it is skipped and then from anything else $search_for is matched (in your case it's specialtext).
Jezzabeanz quite got it except you can simplify it still with:
return preg_replace("/^def/", $replace_with, $content);
If you just want to change the text between the the a tags then a regular expression works wonders.
Here is something I used when I was pulling data from emails sent to me:
(?<=">)(.*?\w)(?=<\/a)
returns "specialtext"
It also returns "specialtext test" if there is whitespace.
Regular expressions are definitely the way to go.
$subject = "abcdef";
$pattern = '/^def/';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3);
print_r($matches);
?>
Source
And then do a replace on the returned matches.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Finetune Regex to skip tags
Currently my function looks like this. It converts plain text URLs into HTML links.
function UrlsToLinks($text){
return preg_replace('#(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)#', '$1', $text);
}
But there are some problems. What I'm trying to do is skip existing links, the src attribute in <img> tags, etc.. Can't figure out what I need to modify in this function.
This would work, assuming that the URLs we want to replace are not already inside a tag.
function UrlsToLinks($text){
$matches = array();
$strippedText = strip_tags($text);
preg_match_all('#(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)#', $strippedText, $matches);
foreach ($matches[0] as $match) {
if (filter_var($match, FILTER_VALIDATE_URL)) {
$text = str_replace($match, ''.$match.'', $text);
}
}
return $text;
}