PHPのお勉強!

PHP TOP

strpos

(PHP 4, PHP 5, PHP 7, PHP 8)

strpos文字列内の部分文字列が最初に現れる場所を見つける

説明

strpos(string $haystack, string $needle, int $offset = 0): int|false

文字列 haystack の中で、 needle が最初に現れる位置を探します。

パラメータ

haystack

検索対象の文字列。

needle

検索する文字列。

PHP 8.0.0 より前のバージョンでは、needle が文字列でない場合、 数値に変換され、文字の通常の値として扱われていました。 この振る舞いは PHP 7.3.0 以降では推奨されないので、 この機能を使用しないことを強く推奨します。 意図した動作に依存する場合、 needle を string に明示的にキャストするか、 明示的に chr() 関数を呼び出すべきでしょう。

offset

指定すると、文字列内での検索開始位置がその位置になります。 負の数を指定すると、文字列の末尾からこの数だけ戻った場所から検索を開始します。

戻り値

needle が見つかった位置を、 haystack 文字列の先頭 (offset の値とは無関係) からの相対位置で返します。 文字列の開始位置は 0 であり、1 ではないことに注意しましょう。

needle が見つからない場合は false を返します。

警告

この関数は論理値 false を返す可能性がありますが、false として評価される値を返す可能性もあります。 詳細については 論理値の セクションを参照してください。この関数の返り値を調べるには ===演算子 を 使用してください。

変更履歴

バージョン 説明
8.0.0 needle は、空文字列を受け入れるようになりました。
8.0.0 needle に数値を渡すことはサポートされなくなりました。
7.3.0 needle に数値を渡すことは非推奨になりました。
7.1.0 負の offset をサポートするようになりました。

例1 === の使用

<?php
$mystring
= 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);

// === を使用していることに注目しましょう。単純に == を使ったのでは
// 期待通りに動作しません。なぜなら 'a' が 0 番目 (最初) の文字だからです。
if ($pos === false) {
echo
"文字列 '$findme' は、文字列 '$mystring' の中で見つかりませんでした";
} else {
echo
"文字列 '$findme' が文字列 '$mystring' の中で見つかりました";
echo
" 見つかった位置は $pos です";
}
?>

例2 !== の使用

<?php
$mystring
= 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);

// !== 演算子も使用可能です。ここで != を使っても期待通りに動作しません。
// なぜなら 'a' が 0 番目の文字だからです。(0 != false) を評価すると
// false になってしまいます。
if ($pos !== false) {
echo
"文字列 '$findme' が文字列 '$mystring' の中で見つかりました";
echo
" 見つかった位置は $pos です";
} else {
echo
"文字列 '$findme' は、文字列 '$mystring' の中で見つかりませんでした";
}
?>

例3 オフセットの使用

<?php
// オフセット以前の内容を無視して文字を探すこともできます。
$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a', 1); // $pos は 0 ではなく 7 となります。
?>

注意

注意: この関数はバイナリデータに対応しています。

参考

  • stripos() - 大文字小文字を区別せずに文字列が最初に現れる位置を探す
  • str_contains() - 指定された部分文字列が、文字列に含まれるかを調べる
  • str_ends_with() - 文字列が、指定された文字列で終わるかを調べる。
  • str_starts_with() - 文字列が指定された部分文字列で始まるかを調べる
  • strrpos() - 文字列中に、ある部分文字列が最後に現れる場所を探す
  • strripos() - 文字列中で、特定の(大文字小文字を区別しない)文字列が最後に現れた位置を探す
  • strstr() - 文字列が最初に現れる位置を見つける
  • strpbrk() - 文字列の中から任意の文字を探す
  • substr() - 文字列の一部分を返す
  • preg_match() - 正規表現によるマッチングを行う

add a note

User Contributed Notes 35 notes

up
221
Suggested re-write for pink WARNING box
16 years ago
WARNING

As strpos may return either FALSE (substring absent) or 0 (substring at start of string), strict versus loose equivalency operators must be used very carefully.

To know that a substring is absent, you must use:

=== FALSE

To know that a substring is present (in any position including 0), you can use either of:

!== FALSE (recommended)
> -1 (note: or greater than any negative number)

To know that a substring is at the start of the string, you must use:

=== 0

To know that a substring is in any position other than the start, you can use any of:

> 0 (recommended)
!= 0 (note: but not !== 0 which also equates to FALSE)
!= FALSE (disrecommended as highly confusing)

Also note that you cannot compare a value of "" to the returned value of strpos. With a loose equivalence operator (== or !=) it will return results which don't distinguish between the substring's presence versus position. With a strict equivalence operator (=== or !==) it will always return false.
up
29
fabio at naoimporta dot com
8 years ago
It is interesting to be aware of the behavior when the treatment of strings with characters using different encodings.

<?php
# Works like expected. There is no accent
var_dump(strpos("Fabio", 'b'));
#int(2)

# The "á" letter is occupying two positions
var_dump(strpos("Fábio", 'b')) ;
#int(3)

# Now, encoding the string "Fábio" to utf8, we get some "unexpected" outputs. Every letter that is no in regular ASCII table, will use 4 positions(bytes). The starting point remains like before.
# We cant find the characted, because the haystack string is now encoded.
var_dump(strpos(utf8_encode("Fábio"), 'á'));
#bool(false)

# To get the expected result, we need to encode the needle too
var_dump(strpos(utf8_encode("Fábio"), utf8_encode('á')));
#int(1)

# And, like said before, "á" occupies 4 positions(bytes)
var_dump(strpos(utf8_encode("Fábio"), 'b'));
#int(5)
up
24
martijn at martijnfrazer dot nl
12 years ago
This is a function I wrote to find all occurrences of a string, using strpos recursively.

<?php
function strpos_recursive($haystack, $needle, $offset = 0, &$results = array()) {
$offset = strpos($haystack, $needle, $offset);
if(
$offset === false) {
return
$results;
} else {
$results[] = $offset;
return
strpos_recursive($haystack, $needle, ($offset + 1), $results);
}
}
?>

This is how you use it:

<?php
$string
= 'This is some string';
$search = 'a';
$found = strpos_recursive($string, $search);

if(
$found) {
foreach(
$found as $pos) {
echo
'Found "'.$search.'" in string "'.$string.'" at position <b>'.$pos.'</b><br />';
}
} else {
echo
'"'.$search.'" not found in "'.$string.'"';
}
?>
up
24
mtroy dot student at gmail dot com
12 years ago
when you want to know how much of substring occurrences, you'll use "substr_count".
But, retrieve their positions, will be harder.
So, you can do it by starting with the last occurrence :

function strpos_r($haystack, $needle)
{
if(strlen($needle) > strlen($haystack))
trigger_error(sprintf("%s: length of argument 2 must be <= argument 1", __FUNCTION__), E_USER_WARNING);

$seeks = array();
while($seek = strrpos($haystack, $needle))
{
array_push($seeks, $seek);
$haystack = substr($haystack, 0, $seek);
}
return $seeks;
}

it will return an array of all occurrences a the substring in the string

Example :

$test = "this is a test for testing a test function... blah blah";
var_dump(strpos_r($test, "test"));

// output

array(3) {
[0]=>
int(29)
[1]=>
int(19)
[2]=>
int(10)
}

Paul-antoine
Malézieux.
up
7
m.m.j.kronenburg
8 years ago
<?php

/**
* Find the position of the first occurrence of one or more substrings in a
* string.
*
* This function is simulair to function strpos() except that it allows to
* search for multiple needles at once.
*
* @param string $haystack The string to search in.
* @param mixed $needles Array containing needles or string containing
* needle.
* @param integer $offset If specified, search will start this number of
* characters counted from the beginning of the
* string.
* @param boolean $last If TRUE then the farthest position from the start
* of one of the needles is returned.
* If FALSE then the smallest position from start of
* one of the needles is returned.
**/
function mstrpos($haystack, $needles, $offset = 0, $last = false)
{
if(!
is_array($needles)) { $needles = array($needles); }
$found = false;
foreach(
$needles as $needle)
{
$position = strpos($haystack, (string)$needle, $offset);
if(
$position === false) { continue; }
$exp = $last ? ($found === false || $position > $found) :
(
$found === false || $position < $found);
if(
$exp) { $found = $position; }
}
return
$found;
}

/**
* Find the position of the first (partially) occurrence of a substring in a
* string.
*
* This function is simulair to function strpos() except that it wil return a
* position when the substring is partially located at the end of the string.
*
* @param string $haystack The string to search in.
* @param mixed $needle The needle to search for.
* @param integer $offset If specified, search will start this number of
* characters counted from the beginning of the
* string.
**/
function pstrpos($haystack, $needle, $offset = 0)
{
$position = strpos($haystack, $needle, $offset);
if(
$position !== false) { return $position; }

for(
$i = strlen($needle); $i > 0; $i--)
{
if(
substr($needle, 0, $i) == substr($haystack, -$i))
{ return
strlen($haystack) - $i; }
}
return
false;
}

/**
* Find the position of the first (partially) occurrence of one or more
* substrings in a string.
*
* This function is simulair to function strpos() except that it allows to
* search for multiple needles at once and it wil return a position when one of
* the substrings is partially located at the end of the string.
*
* @param string $haystack The string to search in.
* @param mixed $needles Array containing needles or string containing
* needle.
* @param integer $offset If specified, search will start this number of
* characters counted from the beginning of the
* string.
* @param boolean $last If TRUE then the farthest position from the start
* of one of the needles is returned.
* If FALSE then the smallest position from start of
* one of the needles is returned.
**/
function mpstrpos($haystack, $needles, $offset = 0, $last = false)
{
if(!
is_array($needles)) { $needles = array($needles); }
$found = false;
foreach(
$needles as $needle)
{
$position = pstrpos($haystack, (string)$needle, $offset);
if(
$position === false) { continue; }
$exp = $last ? ($found === false || $position > $found) :
(
$found === false || $position < $found);
if(
$exp) { $found = $position; }
}
return
$found;
}

?>
up
8
greg at spotx dot net
7 years ago
Warning:
this is not unicode safe

strpos($word,'?') in e?ez-> 1
strpos($word,'?') in è?ent-> 2
up
20
rjeggens at ijskoud dot org
12 years ago
I lost an hour before I noticed that strpos only returns FALSE as a boolean, never TRUE.. This means that

strpos() !== false

is a different beast then:

strpos() === true

since the latter will never be true. After I found out, The warning in the documentation made a lot more sense.
up
9
jexy dot ru at gmail dot com
7 years ago
Docs are missing that WARNING is issued if needle is '' (empty string).

In case of empty haystack it just return false:

For example:

<?php
var_dump
(strpos('foo', ''));

var_dump(strpos('', 'foo'));

var_dump(strpos('', ''));
?>

will output:

Warning: strpos(): Empty needle in /in/lADCh on line 3
bool(false)

bool(false)

Warning: strpos(): Empty needle in /in/lADCh on line 7
bool(false)

Note also that warning text may differ depending on php version, see https://3v4l.org/lADCh
up
7
ilaymyhat-rem0ve at yahoo dot com
16 years ago
This might be useful.

<?php
class String{

//Look for a $needle in $haystack in any position
public static function contains(&$haystack, &$needle, &$offset)
{
$result = strpos($haystack, $needle, $offset);
return
$result !== FALSE;
}

//intuitive implementation .. if not found returns -1.
public static function strpos(&$haystack, &$needle, &$offset)
{
$result = strpos($haystack, $needle, $offset);
if (
$result === FALSE )
{
return -
1;
}
return
$result;
}

}
//String
?>
up
2
eef dot vreeland at gmail dot com
7 years ago
To prevent others from staring at the text, note that the wording of the 'Return Values' section is ambiguous.

Let's say you have a string $myString containing 50 'a's except on position 3 and 43, they contain 'b'.
And for this moment, forget that counting starts from 0.

strpos($myString, 'b', 40) returns 43, great.

And now the text: "Returns the position of where the needle exists relative to the beginning of the haystack string (independent of offset)."

So it doesn't really matter what offset I specify; I'll get the REAL position of the first occurrence in return, which is 3?

... no ...

"independent of offset" means, you will get the REAL positions, thus, not relative to your starting point (offset).

Substract your offset from strpos()'s answer, then you have the position relative to YOUR offset.
up
3
user at nomail dot com
17 years ago
This is a bit more useful when scanning a large string for all occurances between 'tags'.

<?php
function getStrsBetween($s,$s1,$s2=false,$offset=0) {
/*====================================================================
Function to scan a string for items encapsulated within a pair of tags

getStrsBetween(string, tag1, <tag2>, <offset>

If no second tag is specified, then match between identical tags

Returns an array indexed with the encapsulated text, which is in turn
a sub-array, containing the position of each item.

Notes:
strpos($needle,$haystack,$offset)
substr($string,$start,$length)

====================================================================*/

if( $s2 === false ) { $s2 = $s1; }
$result = array();
$L1 = strlen($s1);
$L2 = strlen($s2);

if(
$L1==0 || $L2==0 ) {
return
false;
}

do {
$pos1 = strpos($s,$s1,$offset);

if(
$pos1 !== false ) {
$pos1 += $L1;

$pos2 = strpos($s,$s2,$pos1);

if(
$pos2 !== false ) {
$key_len = $pos2 - $pos1;

$this_key = substr($s,$pos1,$key_len);

if( !
array_key_exists($this_key,$result) ) {
$result[$this_key] = array();
}

$result[$this_key][] = $pos1;

$offset = $pos2 + $L2;
} else {
$pos1 = false;
}
}
} while(
$pos1 !== false );

return
$result;
}
?>
up
10
akarmenia at gmail dot com
13 years ago
My version of strpos with needles as an array. Also allows for a string, or an array inside an array.

<?php
function strpos_array($haystack, $needles) {
if (
is_array($needles) ) {
foreach (
$needles as $str) {
if (
is_array($str) ) {
$pos = strpos_array($haystack, $str);
} else {
$pos = strpos($haystack, $str);
}
if (
$pos !== FALSE) {
return
$pos;
}
}
} else {
return
strpos($haystack, $needles);
}
}

// Test
echo strpos_array('This is a test', array('test', 'drive')); // Output is 10

?>
up
1
marvin_elia at web dot de
6 years ago
Find position of nth occurrence of a string:

function strpos_occurrence(string $string, string $needle, int $occurrence, int $offset = null) {
if((0 < $occurrence) && ($length = strlen($needle))) {
do {
} while ((false !== $offset = strpos($string, $needle, $offset)) && --$occurrence && ($offset += $length));
return $offset;
}
return false;
}
up
4
digitalpbk [at] gmail.com
15 years ago
This function raises a warning if the offset is not between 0 and the length of string:

Warning: strpos(): Offset not contained in string in %s on line %d