PHP Preg Match All fails when matching string with HTML. - php

I'm trying to match the class names in the following.
<section className="content_main_container">
<article className="comment_user_propic">
But only the "article" className is matched.
I've tried the following.
function comments(){
$str = <<<EOT
'<section className="content_main_container">
<article className="comment_user_propic">'
EOT;
return $str;
}
class obfusicate {
function change($str, $prefix){
preg_match_all('#'.$prefix.'="(.*?)"#',$str,$parts);
$array_len = count($parts[1]);
$class_count = 0;
$c_array = [];
foreach($parts[1] as $part){
$rand_name = self::rand_g();
$c_array[$part] = $rand_name;
++$class_count;
$str_1 = str_replace($part, $rand_name, $str);
}
return ['array'=>$c_array, 'string'=>$str_1];
}
}
$obs = new obfusicate;
$result = $obs->change(comments(), 'className');
echo var_dump($result['string']);

Your bug is here:
foreach($parts[1] as $part){
$rand_name = self::rand_g();
$c_array[$part] = $rand_name;
++$class_count;
$str_1 = str_replace($part, $rand_name, $str); //each time you start over replacing from $str and you lose your last $str_1 value
}
return ['array'=>$c_array, 'string'=>$str_1]; //Assigned after the loop so only the last $str_1 value is stored
EDiT: Look at my comment in the last line

Related

PHP function to lowercase each character in a string except for the last one

I'm trying to lowercase every character in a string except for the last one that should be in uppercase.
Here is my code:
function caps_caps($var) {
$var = strrev(ucwords(strrev($var)));
echo $var;
}
caps_caps("HeLlo WOrld"); // should returns "hellO worlD"
This is the easy solution of this problem
function caps_caps($var) {
$var = strrev(ucwords(strrev(strtolower($var))));
echo $var;
}
caps_caps("HeLlo WOrld");
Demo
You also need to convert the string to lowercase first.
function caps_caps($var) {
$var = strrev(ucwords(strrev(strtolower($var))));
echo $var;
}
caps_caps("HeLlo WOrld"); // returns "hellO worlD"
function caps_caps($text) {
$value_to_print = '';
$text = strrev(ucwords(strrev($text)));
$words = explode(' ', $text);
foreach($words as $word){
$word = strtolower($word);
$word[strlen($word)-1] = strtoupper($word[strlen($word)-1]);
$value_to_print .= $word . ' ';
}
echo trim($value_to_print);
}
caps_caps("HeLlo WOrld");
You can try this piece of code.
function uclast($s)
{
$lastCharacterUppar = '';
if ( preg_match('/\s/',$s) ){//If string has space
$explode = explode(' ',$s);
for($i=0;$i<count($explode);$i++){
$l=strlen($explode[$i])-1;
$explode[$i] = strtolower($explode[$i]);
$explode[$i][$l] = strtoupper($explode[$i][$l]);
}
$lastCharacterUppar = implode(' ', $explode);
} else { //if string without space
$l=strlen($s)-1;
$s = strtolower($s);
$s[$l] = strtoupper($s[$l]);
$lastCharacterUppar = $s;
}
return $lastCharacterUppar;
}
$str = 'hey you yo';
echo uclast($str);
Try this, you forgot to do foreach, each elements.
function uclast_words($text, $delimiter = " "){
foreach(explode($delimiter, $text) as $value){
$temp[] = strrev(ucfirst(strrev(strtolower($value))));
}
return implode($delimiter, $temp);
}
print_r(uclast_words("hello world", " "));
I hope this is the answer of your question.
Here is a multibyte safe technique that performs the title-casing with one call instead of two. The string reversal and re-reversal is still necessary.
Code: (Demo)
echo strrev(
mb_convert_case(
strrev('HeLlo WOrld'),
MB_CASE_TITLE
)
);
// hellO worlD

Php search replacer

I have a search String: $str (Something like "test"), a wrap string: $wrap (Something like "|") and a text string: $text (Something like "This is a test Text").
$str is 1 Time in $text. What i want now is a function that will wrap $str with the wrap defined in $wrap and output the modified text (even if $str is more than one time in $text).
But it shall not output the whole text but just 1-2 of the words before $str and then 1-2 of the words after $str and "..." (Only if it isn`t the first or last word). Also it should be case insensitive.
Example:
$str = "Text"
$wrap = "<span>|</span>"
$text = "This is a really long Text where the word Text appears about 3 times Text"
Output would be:
"...long <span>Text</span> where...word <span>Text</span> appears...times <span>Text</span>"
My Code (Obviusly doesnt works):
$tempar = preg_split("/$str/i", $text);
if (count($tempar) <= 2) {
$result = "... ".substr($tempar[0], -7).$wrap.substr($tempar[1], 7)." ...";
} else {
$amount = substr_count($text, $str);
for ($i = 0; $i < $amount; $i++) {
$result = $result.".. ".substr($tempar[$i], -7).$wrap.substr($tempar[$i+1], 0, 7)." ..";
}
}
If you have a tipp or a solution dont hesitate to let me know.
I have taken your approach and made it more flexible. If $str or $wrap changes you could have escaping issues within the regex pattern so I have used preg_quote.
Note that I added $placeholder to make it clearer, but you can use $placeholder = "|" if you don't like [placeholder].
function wrapInString($str, $text, $element = 'span') {
$placeholder = "[placeholder]"; // The string that will be replaced by $str
$wrap = "<{$element}>{$placeholder}</{$element}>"; // Dynamic string that can handle more than just span
$strExp = preg_quote($str, '/');
$matches = [];
$matchCount = preg_match_all("/(\w+\s+)?(\w+\s+)?({$strExp})(\s+\w+)?(\s+\w+)?/i", $text, $matches);
$response = '';
for ($i = 0; $i < $matchCount; $i++) {
if (strlen($matches[1][$i])) {
$response .= '...';
}
if (strlen($matches[2][$i])) {
$response .= $matches[2][$i];
}
$response .= str_replace($placeholder, $matches[3][$i], $wrap);
if (strlen($matches[4][$i])) {
$response .= $matches[4][$i];
}
if (strlen($matches[5][$i]) && $i == $matchCount - 1) {
$response .= '...';
}
}
return $response;
}
$text = "text This is a really long Text where the word Text appears about 3 times Text";
string(107) "<span>text</span> This...long <span>text</span> where...<span>text</span> appears...times <span>text</span>"
To make the replacement case insensitive you can use the i regex option.
If I understand your question correct, just a little bit of implode and explode magic needed
$text = "This is a really long Text where the word Text appears about 3 times Text";
$arr = explode("Text", $text);
print_r(implode('<span>Text</span>', $arr));
If you specifically need to render the span tags using HTML, just write it that way
$arr = explode("Text", $text);
print_r(implode('<span>Text</span>', $arr));
Use patern below to get your word and 1-2 words before and after
/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i
demo
In PHP code it can be:
$str = "Text";
$wrap = "<span>|</span>";
$text = "This is a really long Text where the word Text appears about 3 times Text";
$temp = str_replace('|', $str, $wrap); // <span>Text</span>
// find patern and 1-2 words before and after
// (to make it casesensitive, delete 'i' from patern)
if(preg_match_all('/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i', $text, $match)) {
$res = array_map(function($x) use($str, $temp) { return '... '.str_replace($str, $temp, $x) . ' ...';}, $match[0]);
echo implode(' ', $res);
}

PHP preg_replace string path given

I have issue with preg_replace function in PHP. I cant figure out a pattern and a replacement.
I have this two strings and some code:
$dirname1 = 'hdadas/dasdad/dasd/period_1min';
$dirname2 = 'hdadas/dasdad/dasd/period_1min/abcdrfg.php';
$pieces1 = explode('/', $dirname1);
$pieces2 = explode('/', $dirname2);
$dirname1 = end($pieces1); // output will be period_1min
$dirname2 = end($pieces2); // output will be abcdrfg.php
$output = preg_replace($pattern, $replacement, $dirname1); // or (..,..,$dirname2
echo $output; // i need 1min(without period_) or abcdrfg (without .php)
UPD:
function Cat($dirname)
{
$name = explode('/', $dirname);
$pattern = ???;
$replacement = ???;
return preg_replace($pattern, $replacement, $dirname1);
}
print(Cat('hdadas/dasdad/dasd/period_1min'))); // output need 1min only
print(Cat('hdadas/dasdad/dasd/period_1min/abcdrfg.php'))); // output need abcdrfg only
This should work for you:
(Here I use basename() to get only the last part of the path, then I use pathinfo() to get the last part without the extension. After this I just use preg_replace() to replace everything before the underscore with an empty string)
<?php
$dirname1 = "hdadas/dasdad/dasd/period_1min";
$dirname2 = "hdadas/dasdad/dasd/period_1min/abcdrfg.php";
$dirname1 = pathinfo(basename($dirname1))["filename"];
$dirname2 = pathinfo(basename($dirname2))["filename"];
echo $output = preg_replace("/(.*)_/", "", $dirname1);
?>
output:
1min
abcdrfg
How about this regex /^.+_|\.[^.]+$/:
$dirname1 = 'hdadas/dasdad/dasd/period_1min';
$dirname2 = 'hdadas/dasdad/dasd/period_1min/abcdrfg.php';
$pieces1 = explode('/', $dirname1);
$pieces2 = explode('/', $dirname2);
$dirname1 = end($pieces1); // output will be period_1min
$dirname2 = end($pieces2); // output will be abcdrfg.php
$output = preg_replace('/^.+_|\.[^.]+$/', '', $dirname1); // or (..,..,$dirname2
echo $output,"\n"; // i need 1min(without period_) or abcdrfg (without .php)
$output = preg_replace('/^.+_|\.[^.]+$/', '', $dirname2); // or (..,..,$dirname2
echo $output,"\n"; // i need 1min(without period_) or abcdrfg (without .php)
Output:
1min
abcdrfg

What is the simplest way to split this string using PHP?

I have the below string in PHP.
:guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP
I need to create these variables from the string:
$nick = guest
$user = lbjpewueqi
$host = AF8A326D.E0B4A40D.F85DC93A.IP
What is the best function to use to do this?
Ideally I would like to create some sort of function so I can pass to it the string and what part I want returned.
For example:
$string = "guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP";
echo stringToPart($string, nick);
guest
echo stringToPart($string, nick);
lbjpewueqi
echo stringToPart($string, host);
AF8A326D.E0B4A40D.F85DC93A.IP
Another version:
function stringToPart($string, $part) {
if (preg_match('/^:(.*)!(.*)#(.*)/', $string, $matches)) {
$nick = $matches[1];
$user = $matches[2];
$host = $matches[3];
return isset($$part) ? $$part : null;
}
}
More strict than preg_split solutions - it checks separators order.
Maybe this code may helpful for you
$p = '/[:!#]/';
$s = ":guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP";
print_r( preg_split( $p, $s ), 1 );
You can declare a function like this:
$s = ":guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP";
function stringToPart($str, $part) {
$pat['nick'] = '/:(.*)!/';
$pat['user'] = '/.*!(.*)#/';
$pat['host'] = '/#(.*)/';
preg_match($pat[$part], $str, $m);
if (count($m) > 1) return $m[1];
return null;
}
echo stringToPart($s,'nick')."\n";
echo stringToPart($s,'user')."\n";
echo stringToPart($s,'host')."\n";
The below should do what you're looking for.
$pattern = "/[:!#]/";
$subject = ":guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP";
print_r(preg_split($pattern, $subject));
The pattern is specifying what characters to split on so you could in theory have any amount of characters here if there were other instance you needed to account for different strings being passed in.
To return the values instead of just printing then to the screen use this:
$pattern = "/[:!#]/";
$subject = ":guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP";
$result = preg_split($pattern, $subject));
$nick = $result[1];
$user = $result[2];
$host = $result[3];
stringToPart(':guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP','nick');
function stringToPart($string, $type){
$result['nick']= substr($string,strpos($string,':')+1,(strpos($string,'!')-strpos($string,':')-1));
$result['user']= substr($string,strpos($string,'!')+1,(strpos($string,'#')-strpos($string,'!')-1));
$result['host']= substr($string,strpos($string,'#')+1);
return $result[$type];
}
<?php
function stringToPart($string, $key)
{
$matches = null;
$returnValue = preg_match('/:(?P<nick>[^!]*)!(?P<user>.*?)#(?P<host>.*)/', $string, $matches);
if (isset($matches[$key]))
{
return $matches[$key];
} else
{
return NULL;
}
}
$string = ':guest!lbjpewueqi#AF8A326D.E0B4A40D.F85DC93A.IP';
echo stringToPart($string, "nick");
echo "<br />";
echo stringToPart($string, "user");
echo "<br />";
echo stringToPart($string, "host");
echo "<br />";
?>

highlight the word in the string, if it contains the keyword

how write the script, which menchion the whole word, if it contain the keyword? example: keyword "fun", string - the bird is funny, result - the bird is * funny*. i do the following
$str = "my bird is funny";
$keyword = "fun";
$str = preg_replace("/($keyword)/i","<b>$1</b>",$str);
but it menshions only keyword. my bird is funny
Try this:
preg_replace("/\w*?$keyword\w*/i", "<b>$0</b>", $str)
\w*? matches any word characters before the keyword (as least as possible) and \w* any word characters after the keyword.
And I recommend you to use preg_quote to escape the keyword:
preg_replace("/\w*?".preg_quote($keyword)."\w*/i", "<b>$0</b>", $str)
For Unicode support, use the u flag and \p{L} instead of \w:
preg_replace("/\p{L}*?".preg_quote($keyword)."\p{L}*/ui", "<b>$0</b>", $str)
You can do the following:
$str = preg_replace("/\b([a-z]*${keyword}[a-z]*)\b/i","<b>$1</b>",$str);
Example:
$str = "Its fun to be funny and unfunny";
$keyword = 'fun';
$str = preg_replace("/\b([a-z]*${keyword}[a-z]*)\b/i","<b>$1</b>",$str);
echo "$str"; // prints 'Its <b>fun</b> to be <b>funny</b> and <b>unfunny</b>'
<?php
$str = "my bird is funny";
$keyword = "fun";
$look = explode(' ',$str);
foreach($look as $find){
if(strpos($find, $keyword) !== false) {
if(!isset($highlight)){
$highlight[] = $find;
} else {
if(!in_array($find,$highlight)){
$highlight[] = $find;
}
}
}
}
if(isset($highlight)){
foreach($highlight as $replace){
$str = str_replace($replace,'<b>'.$replace.'</b>',$str);
}
}
echo $str;
?>
Here by am added multi search in a string for your reference
$keyword = ".in#.com#dot.com#1#2#3#4#5#6#7#8#9#one#two#three#four#five#Six#seven#eight#nine#ten#dot.in#dot in#";
$keyword = implode('|',explode('#',preg_quote($keyword)));
$str = "PHP is dot .com the amazon.in 123455454546 dot in scripting language of choice.";
$str = preg_replace("/($keyword)/i","<b>$0</b>",$str);
echo $str;
Basically, since this is HTML, what you have to do is iterate over text nodes and split those containing the search string into up to three nodes (before match, after match and the highlighted match). If "after match" node exist, it must be processed too. Here is a PHP7 example using PHP DOM extension. The following function accepts preg_quoted UTF-8 search string (or regex-conpatible expression like apple|orange). It will enclose every match in a given tag with a given class.
function highlightTextInHTML($regex_compatible_text, $html, $replacement_tag = 'span', $replacement_class = 'highlight') {
$d = new DOMDocument('1.0','utf-8');
$d->loadHTML('<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>' . $html);
$xpath = new DOMXPath($d);
$process_node = function(&$node) use($regex_compatible_text, $replacement_tag, $replacement_class, &$d, &$process_node) {
$i = preg_match("~(?<before>.*?)(?<search>($regex_compatible_text)+)(?<after>.*)~ui", $node->textContent, $m);
if($i) {
$x = $d->createElement($replacement_tag);
$x->setAttribute('class', $replacement_class);
$x->textContent = $m['search'];
$parent_node = $node->parentNode;
$before = null;
$after = null;
if(!empty($m['after'])) {
$after = $d->createTextNode($m['after']);
$parent_node->replaceChild($after, $node);
$parent_node->insertBefore($x, $after);
} else {
$parent_node->replaceChild($x, $node);
}
if(!empty($m['before'])) {
$before = $d->createTextNode($m['before']);
$parent_node->insertBefore($before, $x);
}
if($after) {
$process_node($after);
}
}
};
$node_list = $xpath->query('//text()');
foreach ($node_list as $node) {
$process_node($node);
}
return preg_replace('~(^.*<body>)|(</body>.*$)~mis', '', $d->saveHTML());
}
Search and highlight the word in your string, text, body and paragraph:
<?php $body_text='This is simple code for highligh the word in a given body or text'; //this is the body of your page
$searh_letter = 'this'; //this is the string you want to search for
$result_body = do_Highlight($body_text,$searh_letter); // this is the result with highlight of your search word
echo $result_body; //for displaying the result
function do_Highlight($body_text,$searh_letter){ //function for highlight the word in body of your page or paragraph or string
$length= strlen($body_text); //this is length of your body
$pos = strpos($body_text, $searh_letter); // this will find the first occurance of your search text and give the position so that you can split text and highlight it
$lword = strlen($searh_letter); // this is the length of your search string so that you can add it to $pos and start with rest of your string
$split_search = $pos+$lword;
$string0 = substr($body_text, 0, $pos);
$string1 = substr($body_text,$pos,$lword);
$string2 = substr($body_text,$split_search,$length);
$body = $string0."<font style='color:#FF0000; background-color:white;'>".$string1." </font> ".$string2;
return $body;
} ?>

Categories