Find part of a string and output the whole string - php

I would like to find part of a string and if true I want to ouput the whole of the string that it finds.
Below is an example:
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
if(strstr($Find, $Towns)){
echo outputWholeString($Find, $Towns); // Result: Eccleston.
}
If anyone can shed some light on how to do this as well, and bare in mind that it will not be static values; the $Towns and $Find variables will be dynamically assigned on my live script.

Use explode() and strpos() as
$Towns = "Eccleston, Aberdeen, Glasgow";
$data=explode(",",$Towns);//
$Find = "Eccle";
foreach ($data as $town)
if (strpos($town, $Find) !== false) {
echo $town;
}
DEMO

You have to use strpos() to search for a string inside another one:
if( strpos($Towns, $Find) === false ) {
echo $Towns;
}
Note that you have to use "===" to know if strpos() returned false or 0.

The solution using preg_match function:
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
preg_match("/\b\w*?$Find\w*?\b/", $Towns, $match);
$result = (!empty($match))? $match[0] : "";
print_r($result); // "Eccleston"

Assuming that you will always have $Towns separated by ", " then you could do something like this
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
$TownsArray = explode(", ", $Towns);
foreach($TownsArray as $Town)
{
if(stristr($Find, $Town))
{
echo $Town; break;
}
}
The above code will output the Town once it finds the needle and exit the foreach loop. You could remove the "break;" to continue letting the script run to see if it finds more results.

Using preg_match(), it is possible to search for Eccle and return the Eccleston word.
I use the Pearl Compatible Regular Expression (PCRE) '#\w*' . $Find . '\w*#' in the code below and the demo code.
The # characters are PCRE delimiters. The pattern searched is inside these delimiters. Some people prefer / as delimiter.
The \w indicates word characters.
The * indicates 0 or more repetions of the previous character.
So, the #\w*Eccle\w*# PCRE searches for an string containing Eccle surrounded by one or more word characters (letters)
<?php
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
if (preg_match('#\w*' . $Find . '\w*#', $Towns, $matches)) {
print_r($matches[0]);
}
?>
Running code: http://sandbox.onlinephpfunctions.com/code/4e4026cbbd93deaf8fef0365a7bc6cf6eacc2014
Note: '#\w*' . $Find . '\w*#' is the same as "#\w*$Find\w*#" (note the surrounding single or double quotes). See this.

You were nearly there...
This is probably what you are looking for:
<?php
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
if(stripos($Towns, $Find)) {
echo $Towns;
}
The output is: Eccleston, Aberdeen, Glasgow which is what I would call "the whole string".
If however you only want to output that partly matched part of "the whole string", then take a look at that example:
<?php
$Towns = "Eccleston, Aberdeen, Glasgow";
$Find = "Eccle";
foreach (explode(',', $Towns) as $Town) {
if(stripos($Town, $Find)) {
echo trim($Town);
}
}
The output of that obviously is: Eccleston...
Two general remarks:
the strpos() / stripos() functions are better suited here, since they return only a position instead of the whole matched string which is enough for the given purpose.
the usage of stripos() instead of strpos() performs a case insensitive search, which probably makes sense for the task...

Related

How to find ALL substrings in string using starting and ending words arrays PHP

I've spent my last 4 hours figuring out how to ... I got to ask for your help now.
I'm trying to extract from a text multiple substring match my starting_words_array and ending_words_array.
$str = "Do you see that ? Indeed, I can see that, as well as this." ;
$starting_words_array = array('do','I');
$ending_words_array = array('?',',');
expected output : array ([0] => 'Do you see that ?' [1] => 'I can see that,')
I manage to write a first function that can find the first substring matching one of both arrays items. But i'm not able to find how to loop it in order to get all the substring matching my requirement.
function SearchString($str, $starting_words_array, $ending_words_array ) {
forEach($starting_words_array as $test) {
$pos = strpos($str, $test);
if ($pos===false) continue;
$found = [];
forEach($ending_words_array as $test2) {
$posStart = $pos+strlen($test);
$pos2 = strpos($str, $test2, $posStart);
$found[] = ($pos2!==false) ? $pos2 : INF;
}
$min = min($found);
if ($min !== INF)
return substr($str,$pos,$min-$pos) .$str[$min];
}
return '';
}
Do you guys have any idea about how to achieve such thing ?
I use preg_match for my solution. However, the start and end strings must be escaped with preg_quote. Without that, the solution will be wrong.
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr[] = $match[0];
}
}
return $resArr;
}
The result is what the questioner expects.
If the expressions can occur more than once, preg_match_all must also be used. The regex must be modify.
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*?".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr = array_merge($resArr,$match[0]);
}
}
return $resArr;
}
The resut for the second variant:
array (
0 => "Do you see that ?",
1 => "Indeed,",
2 => "I can see that,",
)
I would definitely use regex and preg_match_all(). I won't give you a full working code example here but I will outline the necessary steps.
First, build a regex from your start-end-pairs like that:
$parts = array_map(
function($start, $end) {
return $start . '.+' . $end;
},
$starting_words_array,
$ending_words_array
);
$regex = '/' . join('|', $parts) . '/i';
The /i part means case insensitive search. Some characters like the ? have a special purpose in regex, so you need to extend above function in order to escape it properly.
You can test your final regex here
Then use preg_match_all() to extract your substrings:
preg_match_all($regex, $str, $matches); // $matches is passed by reference, no need to declare it first
print_r($matches);
The exact structure of your $matches array will be slightly different from what you asked for but you will be able to extract your desired data from it
Benni answer is best way to go - but let just point out the problem in your code if you want to fix those:
strpos is not case sensitive and find also part of words so you need to changes your $starting_words_array = array('do','I'); to $starting_words_array = array('Do','I ');
When finding a substring you use return which exit the function so you want find any other substring. In order to fix that you can define $res = []; at the beginning of the function and replace return substr($str,$pos,... with $res[] = substr($str,$pos,... and at the end return the $res var.
You can see example in 3v4l - in that example you get the output you wanted

PHP preg_replace all text changing

I want to make some changes to the html but I have to follow certain rules.
I have a source code like this;
A beautiful sentence http://www.google.com/test, You can reach here http://www.google.com/test-mi or http://www.google.com/test/aliveli
I need to convert this into the following;
A beautiful sentence http://test.google.com/, You can reach here http://www.google.com/test-mi or http://test.google.com/aliveli
I tried using str_replace;
$html = str_replace('://www.google.com/test','://test.google.com');
When I use it like this, I get an incorrect result like;
A beautiful sentence http://test.google.com/, You can reach here http://test.google.com/-mi or http://test.google.com/aliveli
Wrong replace: http://test.google.com/-mi
How can I do this with preg_replace?
With regex you can use a word boundary and a lookahead to prevent replacing at -
$pattern = '~://www\.google\.com/test\b(?!-)~';
$html = preg_replace($pattern, "://test.google.com", $html);
Here is a regex demo at regex101 and a php demo at eval.in
Be aware, that you need to escape certain characters by a backslash from it's special meaning to match them literally when using regex.
It seems you're replacing the subdirectory test to subdomain. Your case seems to be too complicated. But I've given my best to apply some logic which may be reliable or may not be unless your string stays with the same structure. But you can give a try with this code:
$html = "A beautiful sentence http://www.google.com/test, You can reach here http://www.google.com/test-mi or http://www.google.com/test/aliveli";
function set_subdomain_string($html, $subdomain_word) {
$html = explode(' ', $html);
foreach($html as &$value) {
$parse_html = parse_url($value);
if(count($parse_html) > 1) {
$path = preg_replace('/[^0-9a-zA-Z\/-_]/', '', $parse_html['path']);
preg_match('/[^0-9a-zA-Z\/-_]/', $parse_html['path'], $match);
if(preg_match_all('/(test$|test\/)/', $path)) {
$path = preg_replace('/(test$|test\/)/', '', $path);
$host = preg_replace('/www/', 'test', $parse_html['host']);
$parse_html['host'] = $host;
if(!empty($match)) {
$parse_html['path'] = $path . $match[0];
} else {
$parse_html['path'] = $path;
}
unset($parse_html['scheme']);
$url_string = "http://" . implode('', $parse_html);
$value = $url_string;
}
}
unset($value);
}
$html = implode(' ', $html);
return $html;
}
echo "<p>{$html}</p>";
$modified_html = set_subdomain_string($html, 'test');
echo "<p>{$modified_html}</p>";
Hope it helps.
If the sentence is the only case in your problem you don't need to start struggling with preg_replace.
Just change your str_replace() functioin call to the following(with the ',' at the end of search string section):
$html = str_replace('://www.google.com/test,','://test.google.com/,');
This matches the first occurance of desired search parameter, and for the last one in your target sentence, add this(Note the '/' at the end):
$html = str_replace('://www.google.com/test/','://test.google.com/');
update:
Use these two:
$targetStr = preg_replace("/:\/\/www.google.com\/test[\s\/]/", "://test.google.com/", $targetStr);
It will match against all but the ones with comma at the end. For those, use you sould use the following:
$targetStr = preg_replace("/:\/\/www.google.com\/test,/", "://test.google.com/,", $targetStr);

Getting a word after a specific character in PHP

I want to get the words in a string where a specific character stands before, in this case, its the : character.
textexjkladjladf :theword texttextext :otherword :anotherword
From this snippet the expected output will be:
theword
otherword
anotherword
How do i do this with PHP?
You can use regular expression:
$string = "textexjkladjladf :theword texttextext :otherword :anotherword";
$matches = array();
preg_match_all('/(?<=:)\w+/', $string, $matches);
foreach ($matches[0] as $item) {
echo $item."<br />";
}
Output is:
theword
otherword
anotherword
The array what you want is the $matches[0]
Another way of getting those words without Regular Expression can be:
Use explode(' ',$str) to get all the words.
Then loop the words and check which one starts with ':'.
try
$str = 'textexjkladjladf :theword texttextext :otherword :anotherword';
$tab = exlode(':',$str);
print_r($tab);
//if echo entry 0 =>
echo $tab[0]; // => textexjkladjladf

mb_eregi_replace multiple matches get them

$string = 'test check one two test3';
$result = mb_eregi_replace ( 'test|test2|test3' , '<$1>' ,$string ,'i');
echo $result;
This should deliver: <test> check one two <test3>
Is it possible to get, that test and test3 was found, without using another match function ?
You can use preg_replace_callback instead:
$string = 'test check one two test3';
$matches = array();
$result = preg_replace_callback('/test|test2|test3/i' , function($match) use ($matches) {
$matches[] = $match;
return '<'.$match[0].'>';
}, $string);
echo $result;
Here preg_replace_callback will call the passed callback function for each match of the pattern (note that its syntax differs from POSIX). In this case the callback function is an anonymous function that adds the match to the $matches array and returns the substitution string that the matches are to be replaced by.
Another approach would be to use preg_split to split the string at the matched delimiters while also capturing the delimiters:
$parts = preg_split('/test|test2|test3/i', $string, null, PREG_SPLIT_DELIM_CAPTURE);
The result is an array of alternating non-matching and matching parts.
As far as I know, eregi is deprecated.
You could do something like this:
<?php
$str = 'test check one two test3';
$to_match = array("test", "test2", "test3");
$rep = array();
foreach($to_match as $val){
$rep[$val] = "<$val>";
}
echo strtr($str, $rep);
?>
This too allows you to easily add more strings to replace.
Hi following function used to found the any word from string
<?php
function searchword($string, $words)
{
$matchFound = count($words);// use tha no of word you want to search
$tempMatch = 0;
foreach ( $words as $word )
{
preg_match('/'.$word.'/',$string,$matches);
//print_r($matches);
if(!empty($matches))
{
$tempMatch++;
}
}
if($tempMatch==$matchFound)
{
return "found";
}
else
{
return "notFound";
}
}
$string = "test check one two test3";
/*** an array of words to highlight ***/
$words = array('test', 'test3');
$string = searchword($string, $words);
echo $string;
?>
If your string is utf-8, you could use preg_replace instead
$string = 'test check one two test3';
$result = preg_replace('/(test3)|(test2)|(test)/ui' , '<$1>' ,$string);
echo $result;
Oviously with this kind of data to match the result will be suboptimal
<test> check one two <test>3
You'll need a longer approach than a direct search and replace with regular expressions (surely if your patterns are prefixes of other patterns)
To begin with, the code you want to enhance does not seem to comply with its initial purpose (not at least in my computer). You can try something like this:
$string = 'test check one two test3';
$result = mb_eregi_replace('(test|test2|test3)', '<\1>', $string);
echo $result;
I've removed the i flag (which of course makes little sense here). Still, you'd still need to make the expression greedy.
As for the original question, here's a little proof of concept:
function replace($match){
$GLOBALS['matches'][] = $match;
return "<$match>";
}
$string = 'test check one two test3';
$matches = array();
$result = mb_eregi_replace('(test|test2|test3)', 'replace(\'\1\')', $string, 'e');
var_dump($result, $matches);
Please note this code is horrible and potentially insecure. I'd honestly go with the preg_replace_callback() solution proposed by Gumbo.

Checking if any of the strings in an array matches a string

I'm trying to find out if a string matches any of my bad words in my array IE:
$badWords = Array('bad', 'words', 'go', 'here');
$strToCheck = "checking this string if any of the bad words appear";
if (strpos($strToCheck, $badWords)) {
// bad word found
}
the issue is strpos can only check for a string and not an array, is there a method of doing this without looping through the array of badwords?
Not exactly, since all solutions inevitably must loop over your array, even if it's "behind the scenes". You can make a regular expression out of $badWords, but the runtime complexity will probably not be affected. Anyway, here's my regex suggestion:
$badWordsEscaped = array_map('preg_quote', $badWords);
$regex = '/'.implode('|', $badWordsEscaped).'/';
if(preg_match($regex, $strToCheck)) {
//bad word found
}
Note that I've escaped the words to protect against regex-injections, if they contain any special regex characters such as / or .
array_intersect() gives you the list of matching words:
if (count(array_intersect(preg_split('/\s+/', $strToCheck), $badWords))) {
// ...
}
in_array.
Read question wrong.
Simplest implementation is to call strpos() for each of the badwords:
<?php
$ok = TRUE;
foreach($badwords AS $word)
{
if( strpos($strToCheck, $word) )
{
$ok = FALSE;
break;
}
}
?>
Try This..
$badWords = array('hello','bad', 'words', 'go', 'here');
$strToCheck = 'i am string to check and see if i can find any bad words here';
//Convert String to an array
$strToCheck = explode(' ',$strToCheck);
foreach($badWords as $bad) {
if(in_array($bad, $strToCheck)) {
echo $bad.'<br/>';
}
}
the above code will return all matched bad words, you can further extend it to implement your own logic like replacing the bad words etc.

Categories