Related
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I need a function that returns the substring between two words (or two characters).
I'm wondering whether there is a php function that achieves that. I do not want to think about regex (well, I could do one but really don't think it's the best way to go). Thinking of strpos and substr functions.
Here's an example:
$string = "foo I wanna a cake foo";
We call the function: $substring = getInnerSubstring($string,"foo");
It returns: " I wanna a cake ".
Update:
Well, till now, I can just get a substring beteen two words in just one string, do you permit to let me go a bit farther and ask if I can extend the use of getInnerSubstring($str,$delim) to get any strings that are between delim value, example:
$string =" foo I like php foo, but foo I also like asp foo, foo I feel hero foo";
I get an array like {"I like php", "I also like asp", "I feel hero"}.
If the strings are different (ie: [foo] & [/foo]), take a look at this post from Justin Cook.
I copy his code below:
function get_string_between($string, $start, $end){
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
return substr($string, $ini, $len);
}
$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');
echo $parsed; // (result = dog)
Regular expressions is the way to go:
$str = 'before-str-after';
if (preg_match('/before-(.*?)-after/', $str, $match) == 1) {
echo $match[1];
}
onlinePhp
function getBetween($string, $start = "", $end = ""){
if (strpos($string, $start)) { // required if $start not exist in $string
$startCharCount = strpos($string, $start) + strlen($start);
$firstSubStr = substr($string, $startCharCount, strlen($string));
$endCharCount = strpos($firstSubStr, $end);
if ($endCharCount == 0) {
$endCharCount = strlen($firstSubStr);
}
return substr($firstSubStr, 0, $endCharCount);
} else {
return '';
}
}
Sample use:
echo getBetween("abc","a","c"); // returns: 'b'
echo getBetween("hello","h","o"); // returns: 'ell'
echo getBetween("World","a","r"); // returns: ''
use strstr php function twice.
$value = "This is a great day to be alive";
$value = strstr($value, "is"); //gets all text from needle on
$value = strstr($value, "be", true); //gets all text before needle
echo $value;
outputs:
"is a great day to"
function getInnerSubstring($string,$delim){
// "foo a foo" becomes: array(""," a ","")
$string = explode($delim, $string, 3); // also, we only need 2 items at most
// we check whether the 2nd is set and return it, otherwise we return an empty string
return isset($string[1]) ? $string[1] : '';
}
Example of use:
var_dump(getInnerSubstring('foo Hello world foo','foo'));
// prints: string(13) " Hello world "
If you want to remove surrounding whitespace, use trim. Example:
var_dump(trim(getInnerSubstring('foo Hello world foo','foo')));
// prints: string(11) "Hello world"
function getInbetweenStrings($start, $end, $str){
$matches = array();
$regex = "/$start([a-zA-Z0-9_]*)$end/";
preg_match_all($regex, $str, $matches);
return $matches[1];
}
for examle you want the array of strings(keys) between ## in following
example, where '/' doesn't fall in-between
$str = "C://##ad_custom_attr1##/##upn##/##samaccountname##";
$str_arr = getInbetweenStrings('##', '##', $str);
print_r($str_arr);
I like the regular expression solutions but none of the others suit me.
If you know there is only gonna be 1 result you can use the following:
$between = preg_replace('/(.*)BEFORE(.*)AFTER(.*)/s', '\2', $string);
Change BEFORE and AFTER to the desired delimiters.
Also keep in mind this function will return the whole string in case nothing matched.
This solution is multiline but you can play with the modifiers depending on your needs.
Not a php pro. but i recently ran into this wall too and this is what i came up with.
function tag_contents($string, $tag_open, $tag_close){
foreach (explode($tag_open, $string) as $key => $value) {
if(strpos($value, $tag_close) !== FALSE){
$result[] = substr($value, 0, strpos($value, $tag_close));;
}
}
return $result;
}
$string = "i love cute animals, like [animal]cat[/animal],
[animal]dog[/animal] and [animal]panda[/animal]!!!";
echo "<pre>";
print_r(tag_contents($string , "[animal]" , "[/animal]"));
echo "</pre>";
//result
Array
(
[0] => cat
[1] => dog
[2] => panda
)
A vast majority of answers here don't answer the edited part, I guess they were added before. It can be done with regex, as one answer mentions. I had a different approach.
This function searches $string and finds the first string between $start and $end strings, starting at $offset position. It then updates the $offset position to point to the start of the result. If $includeDelimiters is true, it includes the delimiters in the result.
If the $start or $end string are not found, it returns null. It also returns null if $string, $start, or $end are an empty string.
function str_between(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?string
{
if ($string === '' || $start === '' || $end === '') return null;
$startLength = strlen($start);
$endLength = strlen($end);
$startPos = strpos($string, $start, $offset);
if ($startPos === false) return null;
$endPos = strpos($string, $end, $startPos + $startLength);
if ($endPos === false) return null;
$length = $endPos - $startPos + ($includeDelimiters ? $endLength : -$startLength);
if (!$length) return '';
$offset = $startPos + ($includeDelimiters ? 0 : $startLength);
$result = substr($string, $offset, $length);
return ($result !== false ? $result : null);
}
The following function finds all strings that are between two strings (no overlaps). It requires the previous function, and the arguments are the same. After execution, $offset points to the start of the last found result string.
function str_between_all(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?array
{
$strings = [];
$length = strlen($string);
while ($offset < $length)
{
$found = str_between($string, $start, $end, $includeDelimiters, $offset);
if ($found === null) break;
$strings[] = $found;
$offset += strlen($includeDelimiters ? $found : $start . $found . $end); // move offset to the end of the newfound string
}
return $strings;
}
Examples:
str_between_all('foo 1 bar 2 foo 3 bar', 'foo', 'bar') gives [' 1 ', ' 3 '].
str_between_all('foo 1 bar 2', 'foo', 'bar') gives [' 1 '].
str_between_all('foo 1 foo 2 foo 3 foo', 'foo', 'foo') gives [' 1 ', ' 3 '].
str_between_all('foo 1 bar', 'foo', 'foo') gives [].
If you're using foo as a delimiter, then look at explode()
<?php
function getBetween($content,$start,$end){
$r = explode($start, $content);
if (isset($r[1])){
$r = explode($end, $r[1]);
return $r[0];
}
return '';
}
?>
Example:
<?php
$content = "Try to find the guy in the middle with this function!";
$start = "Try to find ";
$end = " with this function!";
$output = getBetween($content,$start,$end);
echo $output;
?>
This will return "the guy in the middle".
Simple, short, and sweet. It's up to you to make any enhancements.
function getStringBetween($str, $start, $end)
{
$pos1 = strpos($str, $start);
$pos2 = strpos($str, $end);
return substr($str, $pos1+1, $pos2-($pos1+1));
}
If you have multiple recurrences from a single string and you have different [start] and [\end] pattern.
Here's a function which output an array.
function get_string_between($string, $start, $end){
$split_string = explode($end,$string);
foreach($split_string as $data) {
$str_pos = strpos($data,$start);
$last_pos = strlen($data);
$capture_len = $last_pos - $str_pos;
$return[] = substr($data,$str_pos+1,$capture_len);
}
return $return;
}
Here's a function
function getInnerSubstring($string, $boundstring, $trimit=false) {
$res = false;
$bstart = strpos($string, $boundstring);
if ($bstart >= 0) {
$bend = strrpos($string, $boundstring);
if ($bend >= 0 && $bend > $bstart)
$res = substr($string, $bstart+strlen($boundstring), $bend-$bstart-strlen($boundstring));
}
return $trimit ? trim($res) : $res;
}
Use it like
$string = "foo I wanna a cake foo";
$substring = getInnerSubstring($string, "foo");
echo $substring;
Output (note that it returns spaces in front and at the and of your string if exist)
I wanna a cake
If you want to trim result use function like
$substring = getInnerSubstring($string, "foo", true);
Result: This function will return false if $boundstring was not found in $string or if $boundstring exists only once in $string, otherwise it returns substring between first and last occurrence of $boundstring in $string.
References
strpos()
strrpos()
substr()
trim()
Improvement of Alejandro's answer. You can leave the $start or $end arguments empty and it will use the start or end of the string.
echo get_string_between("Hello my name is bob", "my", ""); //output: " name is bob"
private function get_string_between($string, $start, $end){ // Get
if($start != ''){ //If $start is empty, use start of the string
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
}
else{
$ini = 0;
}
if ($end == '') { //If $end is blank, use end of string
return substr($string, $ini);
}
else{
$len = strpos($string, $end, $ini) - $ini; //Work out length of string
return substr($string, $ini, $len);
}
}
private function getStringBetween(string $from, string $to, string $haystack): string
{
$fromPosition = strpos($haystack, $from) + strlen($from);
$toPosition = strpos($haystack, $to, $fromPosition);
$betweenLength = $toPosition - $fromPosition;
return substr($haystack, $fromPosition, $betweenLength);
}
Use:
<?php
$str = "...server daemon started with pid=6849 (parent=6848).";
$from = "pid=";
$to = "(";
echo getStringBetween($str,$from,$to);
function getStringBetween($str,$from,$to)
{
$sub = substr($str, strpos($str,$from)+strlen($from),strlen($str));
return substr($sub,0,strpos($sub,$to));
}
?>
A bit improved code from GarciaWebDev and Henry Wang. If empty $start or $end is given, function returns values from the beginning or to the end of the $string. Also Inclusive option is available, whether we want to include search result or not:
function get_string_between ($string, $start, $end, $inclusive = false){
$string = " ".$string;
if ($start == "") { $ini = 0; }
else { $ini = strpos($string, $start); }
if ($end == "") { $len = strlen($string); }
else { $len = strpos($string, $end, $ini) - $ini;}
if (!$inclusive) { $ini += strlen($start); }
else { $len += strlen($end); }
return substr($string, $ini, $len);
}
I have to add something to the post of Julius Tilvikas. I looked for a solution like this one he described in his post. But i think there is a mistake. I don't get realy the string between two string, i also get more with this solution, because i have to substract the lenght of the start-string. When do this, i realy get the String between two strings.
Here are my changes of his solution:
function get_string_between ($string, $start, $end, $inclusive = false){
$string = " ".$string;
if ($start == "") { $ini = 0; }
else { $ini = strpos($string, $start); }
if ($end == "") { $len = strlen($string); }
else { $len = strpos($string, $end, $ini) - $ini - strlen($start);}
if (!$inclusive) { $ini += strlen($start); }
else { $len += strlen($end); }
return substr($string, $ini, $len);
}
Greetz
V
Try this, Its work for me, get data between test word.
$str = "Xdata test HD01 test 1data";
$result = explode('test',$str);
print_r($result);
echo $result[1];
In PHP's strpos style this will return false if the start mark sm or the end mark em are not found.
This result (false) is different from an empty string that is what you get if there is nothing between the start and end marks.
function between( $str, $sm, $em )
{
$s = strpos( $str, $sm );
if( $s === false ) return false;
$s += strlen( $sm );
$e = strpos( $str, $em, $s );
if( $e === false ) return false;
return substr( $str, $s, $e - $s );
}
The function will return only the first match.
It's obvious but worth mentioning that the function will first look for sm and then for em.
This implies you may not get the desired result/behaviour if em has to be searched first and then the string have to be parsed backward in search of sm.
This is the function I'm using for this. I combined two answers in one function for single or multiple delimiters.
function getStringBetweenDelimiters($p_string, $p_from, $p_to, $p_multiple=false){
//checking for valid main string
if (strlen($p_string) > 0) {
//checking for multiple strings
if ($p_multiple) {
// getting list of results by end delimiter
$result_list = explode($p_to, $p_string);
//looping through result list array
foreach ( $result_list AS $rlkey => $rlrow) {
// getting result start position
$result_start_pos = strpos($rlrow, $p_from);
// calculating result length
$result_len = strlen($rlrow) - $result_start_pos;
// return only valid rows
if ($result_start_pos > 0) {
// cleanying result string + removing $p_from text from result
$result[] = substr($rlrow, $result_start_pos + strlen($p_from), $result_len);
}// end if
} // end foreach
// if single string
} else {
// result start point + removing $p_from text from result
$result_start_pos = strpos($p_string, $p_from) + strlen($p_from);
// lenght of result string
$result_length = strpos($p_string, $p_to, $result_start_pos);
// cleaning result string
$result = substr($p_string, $result_start_pos+1, $result_length );
} // end if else
// if empty main string
} else {
$result = false;
} // end if else
return $result;
} // end func. get string between
For simple use (returns two):
$result = getStringBetweenDelimiters(" one two three ", 'one', 'three');
For getting each row in a table to result array :
$result = getStringBetweenDelimiters($table, '<tr>', '</tr>', true);
an edited version of what Alejandro García Iglesias put.
This allows you to pick a specific location of the string you want to get based on the number of times the result is found.
function get_string_between_pos($string, $start, $end, $pos){
$cPos = 0;
$ini = 0;
$result = '';
for($i = 0; $i < $pos; $i++){
$ini = strpos($string, $start, $cPos);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
$result = substr($string, $ini, $len);
$cPos = $ini + $len;
}
return $result;
}
usage:
$text = 'string has start test 1 end and start test 2 end and start test 3 end to print';
//get $result = "test 1"
$result = $this->get_string_between_pos($text, 'start', 'end', 1);
//get $result = "test 2"
$result = $this->get_string_between_pos($text, 'start', 'end', 2);
//get $result = "test 3"
$result = $this->get_string_between_pos($text, 'start', 'end', 3);
strpos has an additional optional input to start its search at a specific point. so I store the previous position in $cPos so when the for loop checks again, it starts at the end of where it left off.
easy solution using substr
$posStart = stripos($string, $start) + strlen($start);
$length = stripos($string, $end) - $posStart;
$substring = substr($string, $posStart, $length);
Use:
function getdatabetween($string, $start, $end){
$sp = strpos($string, $start)+strlen($start);
$ep = strpos($string, $end)-strlen($start);
$data = trim(substr($string, $sp, $ep));
return trim($data);
}
$dt = "Find string between two strings in PHP";
echo getdatabetween($dt, 'Find', 'in PHP');
I had some problems with the get_string_between() function, used here. So I came with my own version. Maybe it could help people in the same case as mine.
protected function string_between($string, $start, $end, $inclusive = false) {
$fragments = explode($start, $string, 2);
if (isset($fragments[1])) {
$fragments = explode($end, $fragments[1], 2);
if ($inclusive) {
return $start.$fragments[0].$end;
} else {
return $fragments[0];
}
}
return false;
}
wrote these some time back, found it very useful for a wide range of applications.
<?php
// substr_getbykeys() - Returns everything in a source string that exists between the first occurance of each of the two key substrings
// - only returns first match, and can be used in loops to iterate through large datasets
// - arg 1 is the first substring to look for
// - arg 2 is the second substring to look for
// - arg 3 is the source string the search is performed on.
// - arg 4 is boolean and allows you to determine if returned result should include the search keys.
// - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//
function substr_getbykeys($key1, $key2, $source, $returnkeys, $casematters) {
if ($casematters === true) {
$start = strpos($source, $key1);
$end = strpos($source, $key2);
} else {
$start = stripos($source, $key1);
$end = stripos($source, $key2);
}
if ($start === false || $end === false) { return false; }
if ($start > $end) {
$temp = $start;
$start = $end;
$end = $temp;
}
if ( $returnkeys === true) {
$length = ($end + strlen($key2)) - $start;
} else {
$start = $start + strlen($key1);
$length = $end - $start;
}
return substr($source, $start, $length);
}
// substr_delbykeys() - Returns a copy of source string with everything between the first occurance of both key substrings removed
// - only returns first match, and can be used in loops to iterate through large datasets
// - arg 1 is the first key substring to look for
// - arg 2 is the second key substring to look for
// - arg 3 is the source string the search is performed on.
// - arg 4 is boolean and allows you to determine if returned result should include the search keys.
// - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//
function substr_delbykeys($key1, $key2, $source, $returnkeys, $casematters) {
if ($casematters === true) {
$start = strpos($source, $key1);
$end = strpos($source, $key2);
} else {
$start = stripos($source, $key1);
$end = stripos($source, $key2);
}
if ($start === false || $end === false) { return false; }
if ($start > $end) {
$temp = $start;
$start = $end;
$end = $temp;
}
if ( $returnkeys === true) {
$start = $start + strlen($key1);
$length = $end - $start;
} else {
$length = ($end + strlen($key2)) - $start;
}
return substr_replace($source, '', $start, $length);
}
?>
With some error catching. Specifically, most of the functions presented require $end to exist, when in fact in my case I needed it to be optional. Use this is $end is optional, and evaluate for FALSE if $start doesn't exist at all:
function get_string_between( $string, $start, $end ){
$string = " " . $string;
$start_ini = strpos( $string, $start );
$end = strpos( $string, $end, $start+1 );
if ($start && $end) {
return substr( $string, $start_ini + strlen($start), strlen( $string )-( $start_ini + $end ) );
} elseif ( $start && !$end ) {
return substr( $string, $start_ini + strlen($start) );
} else {
return FALSE;
}
}
UTF-8 version of #Alejandro Iglesias answer, will work for non-latin characters:
function get_string_between($string, $start, $end){
$string = ' ' . $string;
$ini = mb_strpos($string, $start, 0, 'UTF-8');
if ($ini == 0) return '';
$ini += mb_strlen($start, 'UTF-8');
$len = mb_strpos($string, $end, $ini, 'UTF-8') - $ini;
return mb_substr($string, $ini, $len, 'UTF-8');
}
$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');
echo $parsed; // (result = dog)
I use
if (count(explode("<TAG>", $input))>1){
$content = explode("</TAG>",explode("<TAG>", $input)[1])[0];
}else{
$content = "";
}
Subtitue <TAG> for whatever delimiter you want.
In my DB i have items names that can be input by users either in the form of Apple MM1 or Banana B-234 or Carl Mm345 (I can't really control too much what users input)
I'd like to be able to convert Carl Mm345 and convert it in Carl MM-345 by using PHP: basically adding a dash or hyphen and uppercase all the letter before dash
function convert_input($string) {
$arr = explode(' ', $string);
if (count($arr) == 1) {
$first = '';
$second = strtoupper($string);
} else {
$first = $arr[0].' ';
$second = strtoupper($arr[1]);
}
$second = str_replace('-', '', $second);
$p = strcspn($second, '0123456789');
$letters = substr($second, 0, $p);
$numbers = substr($second, $p);
$glue = $letters && $numbers ? '-' : '';
return $first.$letters.$glue.$numbers;
}
echo convert_input('mm234');
echo convert_input('Carl Mm345');
echo convert_input('adsf mmmm');
echo convert_input('adsf');
echo convert_input('adsfdsf 123');
echo convert_input('Banana B-234');
I'm not sure exactly what you want, and it's probably more efficient to create a regex expression, but this PHP function seems to accomplish what you want. I generalized the rules you gave in the question (also note that strtoupper makes no difference if the number is upper-cased)
function convert($string) {
$tmp = explode(' ', $string);
$t = '';
$var = str_split($tmp[1]);
for ($i = 0; $i < count($var); $i++) {
if (is_numeric($var[$i])) {
$t .= '-';
}
$t .= strtoupper($var[$i]);
}
return implode('', array($tmp[0])) . $t;
}
I have this link: http://www.youtube.com/e/fIL7Nnlw1LI&feature=related
I need a way in PHP to completely remove everything that is after EACH & in the link.
So it will become : http://www.youtube.com/watch?v=fIL7Nnlw1LI
Attention it could have more than one &
Everything after EACH &, & included, must be deleted from the string
How can I do it in PHP?
You can do this ::
$var = "http://www.youtube.com/e/fIL7Nnlw1LI&feature=related";
$url = explode("&", $var);
$url = $url[0]; //URL is now what you want, the part before First "&"
As I wrote in rpevious your question you can use this 1-line script:
$str = strtok($str,'&');
You can combine strpos with substr:
$spos = strpos($s, "&");
$initial_string = $spos ? substr($s, 0, $spos) : $s;
$url = "http://www.youtube.com/e/fIL7Nnlw1LI&feature=related";
$ampPos = strpos($var, '&');
if ($ampPos !== false)
{
$url = substr($url, 0, $ampPos);
}
Don't use explode, regexp or any other greedy algorithm, it's a waste of resources.
EDIT (Added performance information):
In the preg_match documentation: http://www.php.net/manual/en/function.preg-match.php
Tested explode myself with the following code:
$url = "http://www.youtube.com/e/fIL7Nnlw1LI&feature=related&bla=foo&test=bar";
$time1 = microtime(true);
for ($i = 0; $i < 1000000; $i++)
{
explode("&", $url);
$url = $url[0];
}
$time2 = microtime(true);
echo ($time2 - $time1) . "\n";
$time1 = microtime(true);
for ($i = 0; $i < 1000000; $i++)
{
$ampPos = strpos($url, "&");
if ($ampPos !== false)
$url = substr($url, 0, $ampPos);
}
$time2 = microtime(true);
echo ($time2 - $time1) . "\n";
Gave the following result:
2.47602891922
2.0289251804352
Look at the strpos function, that will give you where the first occurance of a character - in your case & is in a string. From that you can use substr to retrieve the piece of the string you want.
You can use the explode function () to split the string. $url = explode ( "&", $needle ) and then get the first array element.
Firstly, I want to inform that, what I need is the reverse of in_array PHP function.
I need to search all items of array in the string if any of them found, function will return true otherwise return false.
I need the fastest solution to this problem, off course this can be succeeded by iterating the array and using the strpos function.
Any suggestions are welcome.
Example Data:
$string = 'Alice goes to school every day';
$searchWords = array('basket','school','tree');
returns true
$string = 'Alice goes to school every day';
$searchWords = array('basket','cat','tree');
returns false
You should try with a preg_match:
if (preg_match('/' . implode('|', $searchWords) . '/', $string)) return true;
After some comments here a properly escaped solution:
function contains($string, Array $search, $caseInsensitive = false) {
$exp = '/'
. implode('|', array_map('preg_quote', $search))
. ($caseInsensitive ? '/i' : '/');
return preg_match($exp, $string) ? true : false;
}
function searchWords($string,$words)
{
foreach($words as $word)
{
if(stristr($string," " . $word . " ")) //spaces either side to force a word
{
return true;
}
}
return false;
}
Usage:
$string = 'Alice goes to school every day';
$searchWords = array('basket','cat','tree');
if(searchWords($string,$searchWords))
{
//matches
}
Also take note that the function stristr is used to make it not case-sensitive
As per the example of malko, but with properly escaping the values.
function contains( $string, array $search ) {
return 0 !== preg_match(
'/' . implode( '|', preg_quote( $search, '/' ) ) . '/',
$string
);
}
If string can be exploded using space following will work:
var_dump(array_intersect(explode(' ', $str), $searchWords) != null);
OUTPUT: for 2 examples you've provided:
bool(true)
bool(false)
Update:
If string cannot be exploded using space character, then use code like this to split string on any end of word character:
var_dump(array_intersect(preg_split('~\b~', $str), $searchWords) != null);
There is always debate over what is faster so I thought I'd run some tests using different methods.
Tests Run:
strpos
preg_match with foreach loop
preg_match with regex or
indexed search with string to explode
indexed search as array (string already exploded)
Two sets of tests where run. One on a large text document (114,350 words) and one on a small text document (120 words). Within each set, all tests were run 100 times and then an average was taken. Tests did not ignore case, which doing so would have made them all faster. Test for which the index was searched were pre-indexed. I wrote the code for indexing myself, and I'm sure it was less efficient, but indexing for the large file took 17.92 seconds and for the small file it took 0.001 seconds.
Terms searched for included: gazerbeam (NOT found in the document), legally (found in the document), and target (NOT found in the document).
Results in seconds to complete a single test, sorted by speed:
Large File:
0.0000455808639526 (index without explode)
0.0009979915618897 (preg_match using regex or)
0.0011657214164734 (strpos)
0.0023632574081421 (preg_match using foreach loop)
0.0051533532142639 (index with explode)
Small File
0.000003724098205566 (strpos)
0.000005958080291748 (preg_match using regex or)
0.000012607574462891 (preg_match using foreach loop)
0.000021204948425293 (index without explode)
0.000060625076293945 (index with explode)
Notice that strpos is faster than preg_match (using regex or) for small files, but slower for large files. Other factors, such as the number of search terms will of course affect this.
Algorithms Used:
//strpos
$str = file_get_contents('text.txt');
$t = microtime(true);
foreach ($search as $word) if (strpos($str, $word)) break;
$strpos += microtime(true) - $t;
//preg_match
$str = file_get_contents('text.txt');
$t = microtime(true);
foreach ($search as $word) if (preg_match('/' . preg_quote($word) . '/', $str)) break;
$pregmatch += microtime(true) - $t;
//preg_match (regex or)
$str = file_get_contents('text.txt');
$orstr = preg_quote(implode('|', $search));
$t = microtime(true);
if preg_match('/' . $orstr . '/', $str) {};
$pregmatchor += microtime(true) - $t;
//index with explode
$str = file_get_contents('textindex.txt');
$t = microtime(true);
$ar = explode(" ", $str);
foreach ($search as $word) {
$start = 0;
$end = count($ar);
do {
$diff = $end - $start;
$pos = floor($diff / 2) + $start;
$temp = $ar[$pos];
if ($word < $temp) {
$end = $pos;
} elseif ($word > $temp) {
$start = $pos + 1;
} elseif ($temp == $word) {
$found = 'true';
break;
}
} while ($diff > 0);
}
$indexwith += microtime(true) - $t;
//index without explode (already in array)
$str = file_get_contents('textindex.txt');
$found = 'false';
$ar = explode(" ", $str);
$t = microtime(true);
foreach ($search as $word) {
$start = 0;
$end = count($ar);
do {
$diff = $end - $start;
$pos = floor($diff / 2) + $start;
$temp = $ar[$pos];
if ($word < $temp) {
$end = $pos;
} elseif ($word > $temp) {
$start = $pos + 1;
} elseif ($temp == $word) {
$found = 'true';
break;
}
} while ($diff > 0);
}
$indexwithout += microtime(true) - $t;
try this:
$string = 'Alice goes to school every day';
$words = split(" ", $string);
$searchWords = array('basket','school','tree');
for($x = 0,$l = count($words); $x < $l;) {
if(in_array($words[$x++], $searchWords)) {
//....
}
}
Below prints the frequency of number of elements found from the array in the string
function inString($str, $arr, $matches=false)
{
$str = explode(" ", $str);
$c = 0;
for($i = 0; $i<count($str); $i++)
{
if(in_array($str[$i], $arr) )
{$c++;if($matches == false)break;}
}
return $c;
}
Below link will help you : just need to customize as you required.
Check if array element exists in string
customized:
function result_arrayInString($prdterms,208){
if(arrayInString($prdterms,208)){
return true;
}else{
return false;
}
}
This may be helpful to you.
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I need a function that returns the substring between two words (or two characters).
I'm wondering whether there is a php function that achieves that. I do not want to think about regex (well, I could do one but really don't think it's the best way to go). Thinking of strpos and substr functions.
Here's an example:
$string = "foo I wanna a cake foo";
We call the function: $substring = getInnerSubstring($string,"foo");
It returns: " I wanna a cake ".
Update:
Well, till now, I can just get a substring beteen two words in just one string, do you permit to let me go a bit farther and ask if I can extend the use of getInnerSubstring($str,$delim) to get any strings that are between delim value, example:
$string =" foo I like php foo, but foo I also like asp foo, foo I feel hero foo";
I get an array like {"I like php", "I also like asp", "I feel hero"}.
If the strings are different (ie: [foo] & [/foo]), take a look at this post from Justin Cook.
I copy his code below:
function get_string_between($string, $start, $end){
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
return substr($string, $ini, $len);
}
$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');
echo $parsed; // (result = dog)
Regular expressions is the way to go:
$str = 'before-str-after';
if (preg_match('/before-(.*?)-after/', $str, $match) == 1) {
echo $match[1];
}
onlinePhp
function getBetween($string, $start = "", $end = ""){
if (strpos($string, $start)) { // required if $start not exist in $string
$startCharCount = strpos($string, $start) + strlen($start);
$firstSubStr = substr($string, $startCharCount, strlen($string));
$endCharCount = strpos($firstSubStr, $end);
if ($endCharCount == 0) {
$endCharCount = strlen($firstSubStr);
}
return substr($firstSubStr, 0, $endCharCount);
} else {
return '';
}
}
Sample use:
echo getBetween("abc","a","c"); // returns: 'b'
echo getBetween("hello","h","o"); // returns: 'ell'
echo getBetween("World","a","r"); // returns: ''
use strstr php function twice.
$value = "This is a great day to be alive";
$value = strstr($value, "is"); //gets all text from needle on
$value = strstr($value, "be", true); //gets all text before needle
echo $value;
outputs:
"is a great day to"
function getInnerSubstring($string,$delim){
// "foo a foo" becomes: array(""," a ","")
$string = explode($delim, $string, 3); // also, we only need 2 items at most
// we check whether the 2nd is set and return it, otherwise we return an empty string
return isset($string[1]) ? $string[1] : '';
}
Example of use:
var_dump(getInnerSubstring('foo Hello world foo','foo'));
// prints: string(13) " Hello world "
If you want to remove surrounding whitespace, use trim. Example:
var_dump(trim(getInnerSubstring('foo Hello world foo','foo')));
// prints: string(11) "Hello world"
function getInbetweenStrings($start, $end, $str){
$matches = array();
$regex = "/$start([a-zA-Z0-9_]*)$end/";
preg_match_all($regex, $str, $matches);
return $matches[1];
}
for examle you want the array of strings(keys) between ## in following
example, where '/' doesn't fall in-between
$str = "C://##ad_custom_attr1##/##upn##/##samaccountname##";
$str_arr = getInbetweenStrings('##', '##', $str);
print_r($str_arr);
I like the regular expression solutions but none of the others suit me.
If you know there is only gonna be 1 result you can use the following:
$between = preg_replace('/(.*)BEFORE(.*)AFTER(.*)/s', '\2', $string);
Change BEFORE and AFTER to the desired delimiters.
Also keep in mind this function will return the whole string in case nothing matched.
This solution is multiline but you can play with the modifiers depending on your needs.
Not a php pro. but i recently ran into this wall too and this is what i came up with.
function tag_contents($string, $tag_open, $tag_close){
foreach (explode($tag_open, $string) as $key => $value) {
if(strpos($value, $tag_close) !== FALSE){
$result[] = substr($value, 0, strpos($value, $tag_close));;
}
}
return $result;
}
$string = "i love cute animals, like [animal]cat[/animal],
[animal]dog[/animal] and [animal]panda[/animal]!!!";
echo "<pre>";
print_r(tag_contents($string , "[animal]" , "[/animal]"));
echo "</pre>";
//result
Array
(
[0] => cat
[1] => dog
[2] => panda
)
A vast majority of answers here don't answer the edited part, I guess they were added before. It can be done with regex, as one answer mentions. I had a different approach.
This function searches $string and finds the first string between $start and $end strings, starting at $offset position. It then updates the $offset position to point to the start of the result. If $includeDelimiters is true, it includes the delimiters in the result.
If the $start or $end string are not found, it returns null. It also returns null if $string, $start, or $end are an empty string.
function str_between(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?string
{
if ($string === '' || $start === '' || $end === '') return null;
$startLength = strlen($start);
$endLength = strlen($end);
$startPos = strpos($string, $start, $offset);
if ($startPos === false) return null;
$endPos = strpos($string, $end, $startPos + $startLength);
if ($endPos === false) return null;
$length = $endPos - $startPos + ($includeDelimiters ? $endLength : -$startLength);
if (!$length) return '';
$offset = $startPos + ($includeDelimiters ? 0 : $startLength);
$result = substr($string, $offset, $length);
return ($result !== false ? $result : null);
}
The following function finds all strings that are between two strings (no overlaps). It requires the previous function, and the arguments are the same. After execution, $offset points to the start of the last found result string.
function str_between_all(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?array
{
$strings = [];
$length = strlen($string);
while ($offset < $length)
{
$found = str_between($string, $start, $end, $includeDelimiters, $offset);
if ($found === null) break;
$strings[] = $found;
$offset += strlen($includeDelimiters ? $found : $start . $found . $end); // move offset to the end of the newfound string
}
return $strings;
}
Examples:
str_between_all('foo 1 bar 2 foo 3 bar', 'foo', 'bar') gives [' 1 ', ' 3 '].
str_between_all('foo 1 bar 2', 'foo', 'bar') gives [' 1 '].
str_between_all('foo 1 foo 2 foo 3 foo', 'foo', 'foo') gives [' 1 ', ' 3 '].
str_between_all('foo 1 bar', 'foo', 'foo') gives [].
If you're using foo as a delimiter, then look at explode()
<?php
function getBetween($content,$start,$end){
$r = explode($start, $content);
if (isset($r[1])){
$r = explode($end, $r[1]);
return $r[0];
}
return '';
}
?>
Example:
<?php
$content = "Try to find the guy in the middle with this function!";
$start = "Try to find ";
$end = " with this function!";
$output = getBetween($content,$start,$end);
echo $output;
?>
This will return "the guy in the middle".
Simple, short, and sweet. It's up to you to make any enhancements.
function getStringBetween($str, $start, $end)
{
$pos1 = strpos($str, $start);
$pos2 = strpos($str, $end);
return substr($str, $pos1+1, $pos2-($pos1+1));
}
If you have multiple recurrences from a single string and you have different [start] and [\end] pattern.
Here's a function which output an array.
function get_string_between($string, $start, $end){
$split_string = explode($end,$string);
foreach($split_string as $data) {
$str_pos = strpos($data,$start);
$last_pos = strlen($data);
$capture_len = $last_pos - $str_pos;
$return[] = substr($data,$str_pos+1,$capture_len);
}
return $return;
}
Here's a function
function getInnerSubstring($string, $boundstring, $trimit=false) {
$res = false;
$bstart = strpos($string, $boundstring);
if ($bstart >= 0) {
$bend = strrpos($string, $boundstring);
if ($bend >= 0 && $bend > $bstart)
$res = substr($string, $bstart+strlen($boundstring), $bend-$bstart-strlen($boundstring));
}
return $trimit ? trim($res) : $res;
}
Use it like
$string = "foo I wanna a cake foo";
$substring = getInnerSubstring($string, "foo");
echo $substring;
Output (note that it returns spaces in front and at the and of your string if exist)
I wanna a cake
If you want to trim result use function like
$substring = getInnerSubstring($string, "foo", true);
Result: This function will return false if $boundstring was not found in $string or if $boundstring exists only once in $string, otherwise it returns substring between first and last occurrence of $boundstring in $string.
References
strpos()
strrpos()
substr()
trim()
Improvement of Alejandro's answer. You can leave the $start or $end arguments empty and it will use the start or end of the string.
echo get_string_between("Hello my name is bob", "my", ""); //output: " name is bob"
private function get_string_between($string, $start, $end){ // Get
if($start != ''){ //If $start is empty, use start of the string
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
}
else{
$ini = 0;
}
if ($end == '') { //If $end is blank, use end of string
return substr($string, $ini);
}
else{
$len = strpos($string, $end, $ini) - $ini; //Work out length of string
return substr($string, $ini, $len);
}
}
private function getStringBetween(string $from, string $to, string $haystack): string
{
$fromPosition = strpos($haystack, $from) + strlen($from);
$toPosition = strpos($haystack, $to, $fromPosition);
$betweenLength = $toPosition - $fromPosition;
return substr($haystack, $fromPosition, $betweenLength);
}
Use:
<?php
$str = "...server daemon started with pid=6849 (parent=6848).";
$from = "pid=";
$to = "(";
echo getStringBetween($str,$from,$to);
function getStringBetween($str,$from,$to)
{
$sub = substr($str, strpos($str,$from)+strlen($from),strlen($str));
return substr($sub,0,strpos($sub,$to));
}
?>
A bit improved code from GarciaWebDev and Henry Wang. If empty $start or $end is given, function returns values from the beginning or to the end of the $string. Also Inclusive option is available, whether we want to include search result or not:
function get_string_between ($string, $start, $end, $inclusive = false){
$string = " ".$string;
if ($start == "") { $ini = 0; }
else { $ini = strpos($string, $start); }
if ($end == "") { $len = strlen($string); }
else { $len = strpos($string, $end, $ini) - $ini;}
if (!$inclusive) { $ini += strlen($start); }
else { $len += strlen($end); }
return substr($string, $ini, $len);
}
I have to add something to the post of Julius Tilvikas. I looked for a solution like this one he described in his post. But i think there is a mistake. I don't get realy the string between two string, i also get more with this solution, because i have to substract the lenght of the start-string. When do this, i realy get the String between two strings.
Here are my changes of his solution:
function get_string_between ($string, $start, $end, $inclusive = false){
$string = " ".$string;
if ($start == "") { $ini = 0; }
else { $ini = strpos($string, $start); }
if ($end == "") { $len = strlen($string); }
else { $len = strpos($string, $end, $ini) - $ini - strlen($start);}
if (!$inclusive) { $ini += strlen($start); }
else { $len += strlen($end); }
return substr($string, $ini, $len);
}
Greetz
V
Try this, Its work for me, get data between test word.
$str = "Xdata test HD01 test 1data";
$result = explode('test',$str);
print_r($result);
echo $result[1];
In PHP's strpos style this will return false if the start mark sm or the end mark em are not found.
This result (false) is different from an empty string that is what you get if there is nothing between the start and end marks.
function between( $str, $sm, $em )
{
$s = strpos( $str, $sm );
if( $s === false ) return false;
$s += strlen( $sm );
$e = strpos( $str, $em, $s );
if( $e === false ) return false;
return substr( $str, $s, $e - $s );
}
The function will return only the first match.
It's obvious but worth mentioning that the function will first look for sm and then for em.
This implies you may not get the desired result/behaviour if em has to be searched first and then the string have to be parsed backward in search of sm.
This is the function I'm using for this. I combined two answers in one function for single or multiple delimiters.
function getStringBetweenDelimiters($p_string, $p_from, $p_to, $p_multiple=false){
//checking for valid main string
if (strlen($p_string) > 0) {
//checking for multiple strings
if ($p_multiple) {
// getting list of results by end delimiter
$result_list = explode($p_to, $p_string);
//looping through result list array
foreach ( $result_list AS $rlkey => $rlrow) {
// getting result start position
$result_start_pos = strpos($rlrow, $p_from);
// calculating result length
$result_len = strlen($rlrow) - $result_start_pos;
// return only valid rows
if ($result_start_pos > 0) {
// cleanying result string + removing $p_from text from result
$result[] = substr($rlrow, $result_start_pos + strlen($p_from), $result_len);
}// end if
} // end foreach
// if single string
} else {
// result start point + removing $p_from text from result
$result_start_pos = strpos($p_string, $p_from) + strlen($p_from);
// lenght of result string
$result_length = strpos($p_string, $p_to, $result_start_pos);
// cleaning result string
$result = substr($p_string, $result_start_pos+1, $result_length );
} // end if else
// if empty main string
} else {
$result = false;
} // end if else
return $result;
} // end func. get string between
For simple use (returns two):
$result = getStringBetweenDelimiters(" one two three ", 'one', 'three');
For getting each row in a table to result array :
$result = getStringBetweenDelimiters($table, '<tr>', '</tr>', true);
an edited version of what Alejandro García Iglesias put.
This allows you to pick a specific location of the string you want to get based on the number of times the result is found.
function get_string_between_pos($string, $start, $end, $pos){
$cPos = 0;
$ini = 0;
$result = '';
for($i = 0; $i < $pos; $i++){
$ini = strpos($string, $start, $cPos);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
$result = substr($string, $ini, $len);
$cPos = $ini + $len;
}
return $result;
}
usage:
$text = 'string has start test 1 end and start test 2 end and start test 3 end to print';
//get $result = "test 1"
$result = $this->get_string_between_pos($text, 'start', 'end', 1);
//get $result = "test 2"
$result = $this->get_string_between_pos($text, 'start', 'end', 2);
//get $result = "test 3"
$result = $this->get_string_between_pos($text, 'start', 'end', 3);
strpos has an additional optional input to start its search at a specific point. so I store the previous position in $cPos so when the for loop checks again, it starts at the end of where it left off.
easy solution using substr
$posStart = stripos($string, $start) + strlen($start);
$length = stripos($string, $end) - $posStart;
$substring = substr($string, $posStart, $length);
Use:
function getdatabetween($string, $start, $end){
$sp = strpos($string, $start)+strlen($start);
$ep = strpos($string, $end)-strlen($start);
$data = trim(substr($string, $sp, $ep));
return trim($data);
}
$dt = "Find string between two strings in PHP";
echo getdatabetween($dt, 'Find', 'in PHP');
I had some problems with the get_string_between() function, used here. So I came with my own version. Maybe it could help people in the same case as mine.
protected function string_between($string, $start, $end, $inclusive = false) {
$fragments = explode($start, $string, 2);
if (isset($fragments[1])) {
$fragments = explode($end, $fragments[1], 2);
if ($inclusive) {
return $start.$fragments[0].$end;
} else {
return $fragments[0];
}
}
return false;
}
wrote these some time back, found it very useful for a wide range of applications.
<?php
// substr_getbykeys() - Returns everything in a source string that exists between the first occurance of each of the two key substrings
// - only returns first match, and can be used in loops to iterate through large datasets
// - arg 1 is the first substring to look for
// - arg 2 is the second substring to look for
// - arg 3 is the source string the search is performed on.
// - arg 4 is boolean and allows you to determine if returned result should include the search keys.
// - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//
function substr_getbykeys($key1, $key2, $source, $returnkeys, $casematters) {
if ($casematters === true) {
$start = strpos($source, $key1);
$end = strpos($source, $key2);
} else {
$start = stripos($source, $key1);
$end = stripos($source, $key2);
}
if ($start === false || $end === false) { return false; }
if ($start > $end) {
$temp = $start;
$start = $end;
$end = $temp;
}
if ( $returnkeys === true) {
$length = ($end + strlen($key2)) - $start;
} else {
$start = $start + strlen($key1);
$length = $end - $start;
}
return substr($source, $start, $length);
}
// substr_delbykeys() - Returns a copy of source string with everything between the first occurance of both key substrings removed
// - only returns first match, and can be used in loops to iterate through large datasets
// - arg 1 is the first key substring to look for
// - arg 2 is the second key substring to look for
// - arg 3 is the source string the search is performed on.
// - arg 4 is boolean and allows you to determine if returned result should include the search keys.
// - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//
function substr_delbykeys($key1, $key2, $source, $returnkeys, $casematters) {
if ($casematters === true) {
$start = strpos($source, $key1);
$end = strpos($source, $key2);
} else {
$start = stripos($source, $key1);
$end = stripos($source, $key2);
}
if ($start === false || $end === false) { return false; }
if ($start > $end) {
$temp = $start;
$start = $end;
$end = $temp;
}
if ( $returnkeys === true) {
$start = $start + strlen($key1);
$length = $end - $start;
} else {
$length = ($end + strlen($key2)) - $start;
}
return substr_replace($source, '', $start, $length);
}
?>
With some error catching. Specifically, most of the functions presented require $end to exist, when in fact in my case I needed it to be optional. Use this is $end is optional, and evaluate for FALSE if $start doesn't exist at all:
function get_string_between( $string, $start, $end ){
$string = " " . $string;
$start_ini = strpos( $string, $start );
$end = strpos( $string, $end, $start+1 );
if ($start && $end) {
return substr( $string, $start_ini + strlen($start), strlen( $string )-( $start_ini + $end ) );
} elseif ( $start && !$end ) {
return substr( $string, $start_ini + strlen($start) );
} else {
return FALSE;
}
}
UTF-8 version of #Alejandro Iglesias answer, will work for non-latin characters:
function get_string_between($string, $start, $end){
$string = ' ' . $string;
$ini = mb_strpos($string, $start, 0, 'UTF-8');
if ($ini == 0) return '';
$ini += mb_strlen($start, 'UTF-8');
$len = mb_strpos($string, $end, $ini, 'UTF-8') - $ini;
return mb_substr($string, $ini, $len, 'UTF-8');
}
$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');
echo $parsed; // (result = dog)
I use
if (count(explode("<TAG>", $input))>1){
$content = explode("</TAG>",explode("<TAG>", $input)[1])[0];
}else{
$content = "";
}
Subtitue <TAG> for whatever delimiter you want.