PHP replace multiple words - php

So I want to remove everything but some words. I want to keep for an example "car", "circle" and "roof". But remove everything else in a string.
Let's say the string is "I have a car with red one circle at the roof". I wantr to remove everything but "car", "circle" and "roof".
I know there's this one:
$text = preg_replace('/\bHello\b/', 'NEW', $text);
But I can't figure out how to do it with multiple words. I've done this below, but it does the opposite.
$post = $_POST['text'];
$connectors = array( 'array', 'php', 'css' );
$output = implode(' ', array_diff(explode(' ', $post), $connectors));
echo $output;

<?php
$wordsToKeep = array('car', 'circle', 'roof');
$text = 'I have a car with red one circle at the roof';
$words = explode(' ', $text);
$filteredWords = array_intersect($words, $wordsToKeep);
$filteredString = implode(' ', $filteredWords);
$filteredString would then equal car circle roof.
See http://php.net/manual/en/function.array-intersect.php

I suggest the str_word_count() function:
<?php
$string = "Hello fri3nd, you're
looking good today!
I have a car with red one circle at the roof.
An we can add some more _cool_ stuff :D on the roof";
// words to keep
$wordsKeep = array('car', 'circle', 'roof');
// takes care of most cases like spaces, punctuation, etc.
$wordsAll = str_word_count($string, 2, '\'"0123456789');
// remaining words
$wordsRemaining = array_intersect($wordsAll, $wordsKeep);
// maybe do an array_unique() here if you need
// glue the words back to a string
$result = implode(' ', $wordsRemaining);
var_dump($result);

For the sake of reusability, you can create a function like this:
function selector($text,$selected){
$output=explode(' ',$text);
foreach($output as $word){
if (in_array($word,$selected)){
$out[]= trim($word);
}
}
return $out;
}
You get an array like this:
echo implode(' ',selector($post,$connectors));

Related

PHP Spliting then Combining

for example I have a string like this:
$string = 'eat|drink today|tomorrow';
from above string I want to get the result
eat today, eat tomorrow, drink today, drink tomorrow,
what I have to do? I try with split but not so good the result. thanks.
One way is with leveraging explode & implode and as we are explicit here (you know values and size) this would work.
Might be a quicker nicer way with a regular expression to get the first string instantly split, but this was a solution that came in mind at first glance.
$string = 'eat|drink today|tomorrow';
// First split the string by the space between them, then by the pipe in separate arrays.
$removedSpace = explode(' ', $string);
// The action items.
$actions = explode('|', $removedSpace[0]);
// The periods/time of day items.
$dayPeriods = explode('|', $removedSpace[1]);
$final = [];
// Loop through actions and for each day period, generate the string.
foreach ($actions as $action) {
foreach ($dayPeriods as $dayPeriod) {
$final[] = $action . ' ' . $dayPeriod;
}
}
$finalString = implode(', ', $final); // Your desired result in string format without last comma.
[EDIT]
I was writing up my reply while the first reply was published.
Feel free to delete this.
[/EDIT]
You can use explode a several times:
$string = 'eat|drink today|tomorrow';
$tmp = explode(' ',$string); // eat|drink today|tomorrow => [eat|drink, today|tomorrow]
$tmp1 = explode('|',$tmp[0]); // eat|drink => [eat, drink]
$tmp2 = explode('|',$tmp[1]); // today|tomorrow => [today, tomorrow]
foreach($tmp1 as $eat){
foreach($tmp2 as $today){
echo "$eat $today, ";
}
}
Demo
Output:
eat today, eat tomorrow, drink today, drink tomorrow,

Split string in 2 variables but give one variable 2/3 the words

I want to split a string into 2 variables, but give one variable about 75% of the words from the string and the other variable 25%.
I have this code which splits a paragraph from the database in 2, but now I need to give one part 2/3 the words and the other part 1/3 the words. Is this even possible:
Here's my current code:
$pagetext = mysql_result($result, $i, "column");
$thewordamt = str_word_count($pagetext);
$halfwords = $thewordamt / 2;
function limit_words($string, $word_limit) {
$words = explode(" ", $string);
return implode(" ", array_splice($words, 0, $word_limit));
}
$start = limit_words($pagetext, $halfwords); //first part
$end = str_replace($start, '', $pagetext); //second part
I think this explains itself:
$txt = "I met him on a Monday and my heart stood still
Da do ron-ron-ron, da do ron-ron
Somebody told me that his name was Bill
Da do ron-ron-ron, da do ron-ron";
$parts = daDoRunRun($txt, 0.33);
printf('<p>%s</p><p>%s</p>', $parts['short'], $parts['long']);
function daDoRunRun($txt, $short_part_percentage) {
$split_index = floor(str_word_count($txt)*$short_part_percentage);
$words = explode(' ', $txt);
return [
'short' => join(' ', array_splice($words, 0, $split_index)),
'long' => join(' ', $words)
];
}

Link each word of string WITHOUT linking <br>

I'm using a PHP script to link each word of the string:
<?
$str = "hello<br> guys good man";
$arr = explode(' ', $str);
foreach($arr as $value){
echo ''.$value.'';
}
?>
How do I link each word of the string $str without linking the <br>s?
You can just use preg_replace
// More complext string
$str = "hello<br> guys good man Google <br /> hurry";
// Url Template
$template = '%1$s';
// Replace Words
echo preg_replace("/(?!(?:[^<]+>|[^>]+<\/a>))\b([a-z]+)\b/is", sprintf($template, "\\1"), $str);
Output
hello
<br>
guys
good
man
Google
<br />
hurry
Use the strip_tags() function before/in your explode:
$arr = explode (' ', strip_tags($str));
Untested, but start with JvO's code and put the links back into the original string:
$str = "hello<br> guys good man";
$arr = explode (' ', strip_tags($str));
foreach($arr as $value) {
$link = ''.$value.'';
$str = str_replace($value, $link, $str);
}
echo $str;
Note that you can save time by removing duplicates from $arr.
Edit: in fact, you must remove duplicates from $arr, or things will get ugly:
$arr = array_unique(explode (' ', strip_tags($str)));
... and another edit to the original code for an error.
Before you form the link, process the string first:
$proc_val = preg_replace('/<br>/', '', $value);
echo ''.$value.'';
Not sure what you were saying in the comment of Jvo's answer, but you can always use the striptags in the foreach as well and only strip the link part.
foreach($arr as $value){
echo ''.$value.'';
}
So here is the full code:
<?
$str = "hello<br> guys good man";
$arr = explode(' ', $str);
foreach($arr as $value){
echo ''.$value.'';
}
?>
You really should think about what explode(' ', $str) is going to do though.
Any time any HTML tag has attributes to it like <span style="color: red;"> you are going to run into trouble. You should strip_tags first, on the entire string, then process it. Keep an HTML version as a separate string if you need to add stuff later.
Why not just explode the string as you currently are and simply strip the tags in the URL.
$str = "hello<br> guys good man";
$arr = explode(' ', $str);
foreach($arr as $value){
echo ''.$value.'';
}
This will output the following HTML which is what I believe you want.
hello<br>
guys
good
man
If the string is quite long, and can contain any number of tags, including <p>, <h1> and <br> as well as the more correct <br/>, you could consider parsing the lot, and use str_replace:
$string = 'Foo<br/>Hello Bar!';
$DOM = new DOMDocument;
//make sure all breaks are preceded by a space, if not words might be concatenated by accident
$DOM->loadHTML(str_replace('<br', ' <br', $string));
//get all nodes
$nodes = $DOM->getElementsByTagName('*');
//get the text, split it and replace, but keep track of replaced words
$replaced = array();
for ($i = 0, $j = $nodes->length; $i<$j;$i++)
{
$words = explode(' ',$nodes->item($i)->nodeValue);
while($word = array_shift($words))
{
if (!array_key_exists($word, $replaced))
{//avoid replacing twice (and thus creating a link within a link)
$replaced[$word] = true;
$string = str_replace($word, ''.$word.'', $string);
}
}
}
This code is tested and working.

How to bold keyword in php mysql search?

I want want my output like this when I search a keyword like
"programming"
php programming language
How to do this in php mysql?
Any idea?
Just perform a str_replace on the returned text.
$search = 'programming';
// $dbContent = the response from the database
$dbContent = str_replace( $search , '<b>'.$search.'</b>' , $dbContent );
echo $dbContent;
Any instance of "programming", even if as part of a larger word, will be wrapped in <b> tags.
For instances where more than one word are used
$search = 'programming something another';
// $dbContent = the response from the database
$search = explode( ' ' , $search );
function wrapTag($inVal){
return '<b>'.$inVal.'</b>';
}
$replace = array_map( 'wrapTag' , $search );
$dbContent = str_replace( $search , $replace , $dbContent );
echo $dbContent;
This will split the $search into an array at the spaces, and then wrap each match in the <b> tags.
You could use <b> or <strong> tags (See What's the difference between <b> and <strong>, <i> and <em>? for a dicussion about them).
$search = #$_GET['q'];
$trimmed = trim($search);
function highlight($req_field, $trimmed) //$req_field is the field of your table
{
preg_match_all('~\w+~', $trimmed, $m);
if(!$m)
return $req_field;
$re = '~\\b(' . implode('|', $m[0]) . ')\\b~';
return preg_replace($re, '<b>$0</b>', $req_field);
}
print highlight($req_field, $trimmed);
In this way, you can bolden the searched keywords. Its quite easy and works well.
The response is actually a bit more complicated than that. In the common search results use case, there are other factors to consider:
you should take into account uppercase and lowercase (Programming, PROGRAMMING, programming etc);
if your content string is very long, you wouldn't want to return the whole text, but just the searched query and a few words before and after it, for context;
This guy figured it out:
//$h = text
//$n = keywords to find separated by space
//$w = words near keywords to keep
function truncatePreserveWords ($h,$n,$w=5,$tag='b') {
$n = explode(" ",trim(strip_tags($n))); //needles words
$b = explode(" ",trim(strip_tags($h))); //haystack words
$c = array(); //array of words to keep/remove
for ($j=0;$j<count($b);$j++) $c[$j]=false;
for ($i=0;$i<count($b);$i++)
for ($k=0;$k<count($n);$k++)
if (stristr($b[$i],$n[$k])) {
$b[$i]=preg_replace("/".$n[$k]."/i","<$tag>\\0</$tag>",$b[$i]);
for ( $j= max( $i-$w , 0 ) ;$j<min( $i+$w, count($b)); $j++) $c[$j]=true;
}
$o = ""; // reassembly words to keep
for ($j=0;$j<count($b);$j++) if ($c[$j]) $o.=" ".$b[$j]; else $o.=".";
return preg_replace("/\.{3,}/i","...",$o);
}
Works like a charm!

regex to higlight the word part-by-part if it contain the keyword

i've asked same question before here, but now i need to higlight the keywortd in another way, then other part of word. example will be helpful i think
$str = "i like programming very much";
$key = "gram";
i need to get something like pro gram ming
$str = "i like <span class='first'>pro</span><span class='second'>gram</span><span class='firs'>ing</span>"
why preg_replace("/([^\s]*?)(".preg_quote($key).")([^\s]*)/iu","<span class="first">$0</span><span class="second">$1</span><span class="first">$2</span>",$str);
doesn't work?
Thanks
There are some errors, the first group is $1 and not $0 and so on. And you embeded ".
so, instead of :
preg_replace("/([^\s]*?)(".preg_quote($key).")([^\s]*)/iu","<span class="first">$0</span><span class="second">$1</span><span class="first">$2</span>",$str);
You have to do :
preg_replace("/([^\s]*?)(".preg_quote($key).")([^\s]*)/iu","<span class='first'>$1</span><span class='second'>$2</span><span class='first'>$3</span>",$str);
You're in PHP, so consider something like:
$words = explode(' ', "quick brown fox");
$out = array_map(process, $words);
return join(' ', $out);
and define
function process($word) {
$p = strpos($word, 'gram');
if ($p === FALSE) return $word;
/// take apart pieces with substr and friends, reformat in HTML, and return them
$left = substr($word, 0, $p);
$match = substr($word, $p, strlen('gram'));
$right = substr($word, $p+strlen('gram'));
return some_function_of($left, $match, $right);
}
A little more effort, but it does what you want.

Categories