1

Possible Duplicate:
How to parse and process HTML with PHP?
PHP - Get part of string by searching for characters, instead of counting them?

I have a string:

$str = "hello world, this is mars"

and I want an improved strstr that will look like this:

istrstr($str, 'world', 'is')

and the return value will be:

"world, this"

In other words, there is a needle that starts and a needle that ends.

I was just wondering if there is a solution already, or I should just write one myself...

UPDATE:

based on the answers I did this function:

function istrstr($haystack, $needle_start, $needle_end, $include = false) {

    if (!$include) {
        $pos_start = strpos($haystack, $needle_start) + strlen($needle_start);
        $pos_end = strpos($haystack, $needle_end, $pos_start);
        return substr($haystack, $pos_start, $pos_end - $pos_start);
    }

}

for now I just need the excluding version, so I didn't bother doing the including one...

Community
  • 1
  • 1
Moshe Shaham
  • 15,448
  • 22
  • 74
  • 114
  • So you actually want the string between the first matches of the needles? Perhaps your solutions is best found in a regular expression: ```preg_match( "/world(.*)is/i" , $str , $m );``` This would give you all matches though. – Luceos Aug 21 '12 at 08:15
  • You should write it yourself, if only to find out you left out some specs. (for instance: what is the result of `istrstr("world the world sentence is really is world foobar is because world is", 'world','is');`. Probably just use a regexp (yes I know, now you've got 2 problems) – Nanne Aug 21 '12 at 08:15

2 Answers2

10
function from_to($str, $from, $to) {
    return substr(
        $str,
        strpos($str, $from),
        strpos($str, $to) - strpos($str, $from) + strlen($to)
    );
}

This is basic string manipulation. Please read the manual a bit more.


A more robust solution to close all edge cases (and includes documentation):

<?php

/**
 * @param string $string  The string to match against
 * @param string $from    Starting substring, from here
 * @param string $to      Ending substring, to here
 *
 * @return string         Substring containing all the letters from $from to $to inclusive.
 * @throws Exception      In case of $to being found before $from
 */
function from_to($string, $from, $to) {
    //Calculate where each substring is found inside of $string
    $pos_from = strpos($string, $from);
    $pos_to   = strpos($string, $to);

    //The function will break if $to appears before $from, throw an exception.
    if ($pos_from > $pos_to) {
        throw new Exception("'$from' ($pos_from) appears before '$to' ($pos_to)");
    }

    return substr(
        $string,
        $pos_from, //From where the $from starts (first character of $from)
        $pos_to - $pos_from + strlen($to) //To where the $to ends. (last character of $to)
    );
}

$str = "hello world, and this not foo is mars";
try {
    echo from_to($str, 'world', 'hell');
}
catch (Exception $e) {
    //In case 'hell' appeared before 'world'
    echo from_to($str, 'hell', 'world');
}
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • The third argument to [`substr()`](http://www.php.net/manual/en/function.substr.php) should be the length of the string to be returned. – eggyal Aug 21 '12 at 08:17
  • @eggyal: You're right, I just noticed it myself, corrected :) – Madara's Ghost Aug 21 '12 at 08:18
  • Out of interest, will the PHP compiler optimise this so that `$str` does not need to be searched twice for `$from`? Or, with a long input string, would it be wise to explicitly cache the result of that call to `strpos()`? Also, what if `$to` occurs in both the substrings before and after `$from`? One really ought to search only the latter... – eggyal Aug 21 '12 at 08:19
0
function istrstr($haystack, $needle1, $needle2) {
    $pos1=strpos($haystack,$needle1);
    $pos2=strpos($haystack,$needle2);
    return substr($haystack, $pos1, $pos2-$pos1+strlen($needle2));
}
$str = "hello world, this is mars";
echo istrstr($str, 'world', 'is');

Although that will return world, this because the first instance of is in the above sentence is at position 15, in the word this.

Edit:

I'd recommend regexp as @Nanne commented above to make sue you have a $needle2 that's not within a word, if that's what you're after?

Stu
  • 4,160
  • 24
  • 43
  • You are not using $needle1 and $needle2 in your function, and also, `world, this` is the intended result (you should include the `is` inside. – Madara's Ghost Aug 21 '12 at 08:31
  • heh oh yes, oops! fixed the $needle error, thanks. The reason `world th` is returned, and not `world this`, is because the first instance of `is` is actually within the word `this`, not the word `is`, I'll have a think on that issue, but the function works in outputting the text between the first instance of `$needle1` and the first instance of `$needle2`. – Stu Aug 21 '12 at 08:36
  • The point is to include the characters of $to. (I think) OP is aware of the `this` `is` issue. – Madara's Ghost Aug 21 '12 at 08:45
  • Ah, gotcha, thanks, added the answer for completeness, although I think [your answer](http://stackoverflow.com/questions/12050673/php-strstr-with-an-ending-needle/12050866#answer-12050716) is the more comprehensive one – Stu Aug 21 '12 at 09:00