Question about strpos: how to get 2nd occurrence of a string?

PhpString

Php Problem Overview


I understand that this function will get the first occurrence of the string.

But what I want is the 2nd occurrence.

How to go about doing that?

Php Solutions


Solution 1 - Php

I know this question is kind of old, but here's a function I wrote to get the Xth occurrence of a substring, which may be helpful for other people that have this issue and stumble over this thread.

/**
 * Find the position of the Xth occurrence of a substring in a string
 * @param $haystack
 * @param $needle
 * @param $number integer > 0
 * @return int
 */
function strposX($haystack, $needle, $number) {
    if ($number == 1) {
        return strpos($haystack, $needle);
    } elseif ($number > 1) {
        return strpos($haystack, $needle, strposX($haystack, $needle, $number - 1) + strlen($needle));
    } else {
        return error_log('Error: Value for parameter $number is out of range');
    }
}

Or a simplified version:

function strposX($haystack, $needle, $number = 0)
{
    return strpos($haystack, $needle,
        $number > 1 ?
        strposX($haystack, $needle, $number - 1) + strlen($needle) : 0
    );
}

Solution 2 - Php

You need to specify the offset for the start of the search as the optional third parameter and calculate it by starting the search directly after the first occurrence by adding the length of what you're searching for to the location you found it at.

$pos1 = strpos($haystack, $needle);
$pos2 = strpos($haystack, $needle, $pos1 + strlen($needle));

Solution 3 - Php

The recursive function from Smokey_Bud was slowing my script drastically down. Using a regular expression is much faster in this case (for finding any occurence):

function strposX($haystack, $needle, $number)
{
    // decode utf8 because of this behaviour: https://bugs.php.net/bug.php?id=37391
    preg_match_all("/$needle/", utf8_decode($haystack), $matches, PREG_OFFSET_CAPTURE);
    return $matches[0][$number-1][1];
}

// get position of second 'wide'
$pos = strposX('Hello wide wide world', 'wide', 2);

Solution 4 - Php

You can try this, though I haven't tested it out-

$pos = strpos($haystack, $needle, strpos($haystack, $needle)+strlen($needle));

Solution 5 - Php

To find second occurrence of the string you can use the strpos along with "offset" parameter, by adding previous offset to strpos.

$source = "Hello world, how you doing world...world ?";
$find = "world";
$offset = 0;
$findLength = strlen($find);
$occurrence = 0;

while (($offset = strpos($source, $find, $offset))!== false) {
    if ($occurrence ++) {
      break;
    }
    $offset += $findLength; 
}

echo $offset;

You can find all the occurrences by storing offset into an array

while (($offset = strpos($source, $find, $offset))!== false) {
  $occurrences[] = $offset;
  $offset += $findLength; 
}
var_export($occurrences);

Or can get a specific occurrence by matching $occurrence

//find 3rd occurrence
if ($occurrence ++ == 2) {
    break;
}

Solution 6 - Php

Simple is beautiful

function strposX($haystack, $needle, $n = 0)
{
    $offset = 0;

    for ($i = 0; $i < $n; $i++) {
        $pos = strpos($haystack, $needle, $offset);

        if ($pos !== false) {
            $offset = $pos + strlen($needle);
        } else {
            return false;
        }
    }

    return $offset;
}

$offset = strposX($result, "\n", $n);

if ($offset === false) {
    $offset = strlen($result) - 1;
}

Solution 7 - Php

Old question but how about using explode?

$corpus = "how many words are there in a dictionary? I'm not going to count them word by word...";
$looking_for = 'word';
$instance = 2;

$parts = explode($looking_for, $corpus, $instance + 1);
array_pop($parts);
$position = strlen(implode($looking_for, $parts));

Solution 8 - Php

Easily, just do it:

$i = $pos = 0;    
do {
        $pos = strpos( $string, $needle, $pos+1 );
} while( $i++ < $nth);

$nth for your situation is equal to 2.

Solution 9 - Php

function strpos_nth( $haystack, $needle, $occurrence ) 
{
	if ( filter_var( $occurrence, FILTER_VALIDATE_INT, [ "options" => ["min_range"=>1, "max_range"=>strlen($haystack)] ] ) === false)
		return false ;

	$loop     = 0;
	$position = -1;
	while ( $position!==false && ++$loop<=$occurrence ) 
		$position = strpos( $haystack, $needle, ++$position );

	return $position;
}

https://onlinephp.io/c/7d44a

Solution 10 - Php

just worked for me to find if are 2 or more occurrence of a char, then by strlen them i found that exist 2 occurrence ex ( i dont use $matches at all):

$string = '1234|6|#red';

if(strlen(preg_match_all('/|/', $string,$matches, PREG_OFFSET_CAPTURE)) ==2){
			
echo 'i have 2 occurence of char: |';
					
	}

Solution 11 - Php

Old question, but if someone's looking for a way to find occurrences from the END of the string (for example 3rd occurrence of dot from the end) the following function works (didn't want to use oncodes function not to mess with encoding)

$str = "NooooYesYesNo";

function find_occurence_from_end($haystack, $needle, $num) {

    for ($i=1; $i <=$num ; $i++) {

        # first loop return position of needle
        if($i == 1) {
            $pos = strrpos($haystack, $needle);
        }

        # subsequent loops trim haystack to pos and return needle's new position
        if($i != 1) {

            $haystack = substr($haystack, 0, $pos);
            $pos = strrpos($haystack, $needle);

        }

    }

    return $pos;

}

$pos = find_occurence_from_end($str, "Yes", 2);

// 5

It's super simple. Basically each time it finds an occurrence of your needle it "trims" the string to that position. So it keeps on trimming it while returning the latest position each time.

Solution 12 - Php

function substr_Index( $str, $nth ){
	$str2 = '';
	$posTotal = 0;
	for($i=0; $i < $nth; $i++){
		
		if($str2 != ''){
			$str = $str2;
		}
		
		$pos   = strpos($str, ':');
		$str2  = substr($str, $pos+1);
		$posTotal += $pos+1;
		
	}
	return $posTotal-1;
}


echo substr($mystring, substr_Index( $mystring , 2) );

Function returns position of nth delimiter.

Second parameter of substr_Index must be bigger than 0;

To find second occourance use substr_Index( $mystring , 2)

Solution 13 - Php

//Finds nth occourance of string after position of given needle.
//Pass $needle argument as empty string [''] if you want to find from start
//Pass $needle argument as Int to search string from this position

function substr_Index( $string, $needle, $delimiter, $nth ){
	$str2 = '';
	$posf = strpos($string, $needle);
	if($posf !== false){
		$string   = substr($string, $posf);
		$posTotal = $posf;		
	}else{
		$posTotal = 0;
	}
	
	if( is_int($needle) ){
		$posTotal = $needle;
	}

	for($i=0; $i < $nth; $i++){
		
		if($str2 != ''){
			$string = $str2;
		}
			 
		$pos   = strpos($string, $delimiter);
		$str2  = substr($string, $pos + 1);
		$posTotal += $pos+1;
		
	}
	return $posTotal-1;
}
			   
//example (returns part of given string from second [:] next from first [#]  )
$str_ = '..:....:..:....#,61185:9789756130346:0000000:369615:97860510:61436=0000000323636';

echo substr($str_, substr_Index( $str_, '#' , ':', 2) );

Solution 14 - Php

Please check the following code ... it works pretty fine for me.

<?php
    function f_srch ($s1, $par) {
        echo 'Searching for [' . $par . '] in [' . $s1 . ']<br>';
        $k = 0; //while loop
        $i = 0; // counter

        while ($k >= 0) {
            $pos = strpos($s1, $par, $k);
            if ($pos === false) {
                $k=-1;
                echo 'Letter not found'.'<br>';
            } else {
                if ($pos == $k) { 
                    echo 'The position of the letter is '.$pos.'<br>'; 
                    $i++;
                }
                $k++;
            } 
        }
        echo 'The letter was found ' . $i . ' time(s).'.'<br>'; 
    }
    f_srch('i am searching for a letter in this sentence','t');
?>

Solution 15 - Php

http://php.net/strpos

$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a', 1);  // $pos = 7, not 0

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionvfvgView Question on Stackoverflow
Solution 1 - PhpTheKidsWantDjentView Answer on Stackoverflow
Solution 2 - PhpSophie AlpertView Answer on Stackoverflow
Solution 3 - PhponcodeView Answer on Stackoverflow
Solution 4 - PhpSadatView Answer on Stackoverflow
Solution 5 - PhpTofeeqView Answer on Stackoverflow
Solution 6 - Phptom10271View Answer on Stackoverflow
Solution 7 - PhpMaarten WolzakView Answer on Stackoverflow
Solution 8 - PhpHamze GhaemPanahView Answer on Stackoverflow
Solution 9 - PhpelFarmerView Answer on Stackoverflow
Solution 10 - PhpDanView Answer on Stackoverflow
Solution 11 - PhpRobert SinclairView Answer on Stackoverflow
Solution 12 - PhpKadView Answer on Stackoverflow
Solution 13 - PhpTekView Answer on Stackoverflow
Solution 14 - PhpKassabView Answer on Stackoverflow
Solution 15 - PhpLeoView Answer on Stackoverflow