Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】substr_count()関数の使い方

substr_count関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

substr_count関数は、指定された文字列(haystack)の中に、特定の文字列(needle)が何回出現するかをカウントする関数です。この関数は、大文字と小文字を区別してカウントを行います。例えば、長い文章中に特定のキーワードがいくつ含まれているかを調べたい場合や、ログデータから特定のエラーメッセージの発生頻度を知りたい場合などに役立ちます。

この関数は、以下の引数を取ります。 最初の引数 $haystack には、検索の対象となる元の文字列を指定します。 次の引数 $needle には、$haystack の中で探したい部分文字列を指定します。 オプションの3番目の引数 $offset には、文字列のどの位置から検索を開始するかを整数で指定します。デフォルト値は 0 で、文字列の先頭から検索を開始します。 オプションの4番目の引数 $length には、$offset で指定した位置から、どのくらいの長さの範囲内で検索を行うかを整数で指定します。この引数を省略すると、$offset から文字列の最後までが検索対象となります。

戻り値としては、$haystack 内で $needle が見つかった回数を整数で返します。$needle が全く見つからなかった場合は 0 を返します。検索はバイト単位で行われるため、日本語のようなマルチバイト文字を扱う際には、文字数ではなくバイト数で処理されることに注意が必要です。この関数を利用することで、文字列内での部分文字列の出現頻度を手軽に把握することができます。

構文(syntax)

1<?php
2$text = "apple banana apple orange apple";
3$sub = "apple";
4$count = substr_count($text, $sub);
5echo $count; // 3 が出力されます。
6?>

引数(parameters)

string $haystack, string $needle, int $offset = 0, ?int $length = null

  • string $haystack: 検索対象となる文字列
  • string $needle: 検索する部分文字列
  • int $offset = 0: 検索を開始する位置(デフォルトは文字列の先頭)
  • ?int $length = null: 検索する文字列の長さ(デフォルトは残りの全文字列)

戻り値(return)

int

指定された文字列の中に、検索対象の文字列がいくつ含まれているかを整数で返します。

サンプルコード

PHP substr_countでマルチバイト文字をカウントする

1<?php
2
3/**
4 * substr_countの基本的な使い方と、マルチバイト文字列における注意点を示すサンプルコードです。
5 * PHPの標準関数には「mb_substr_count」は存在しませんが、
6 * それを求める意図(マルチバイト文字列における文字単位の出現回数カウント)に応えるため、
7 * カスタム関数「mb_substr_count_char_aware」を併せて提供します。
8 */
9
10// PHPの内部文字エンコーディングをUTF-8に設定することを推奨します。
11// これにより、mb_*関数が正しく動作します。
12mb_internal_encoding('UTF-8');
13
14// --- 1. substr_countの基本的な使い方 (ASCII文字列) ---
15$haystackAscii = "Hello world, hello PHP!";
16$needleAscii = "hello";
17
18// substr_countは、指定された部分文字列が何回出現するかをカウントします。
19// デフォルトでは大文字・小文字を区別します。
20$countAsciiCaseSensitive = substr_count($haystackAscii, $needleAscii);
21echo "ASCII文字列 (大文字小文字区別): '$needleAscii' は '$haystackAscii' に {$countAsciiCaseSensitive} 回出現します。\n"; // 出力: 1
22
23// 大文字・小文字を区別せずにカウントしたい場合は、文字列を変換してからカウントします。
24$countAsciiCaseInsensitive = substr_count(mb_strtolower($haystackAscii), mb_strtolower($needleAscii));
25echo "ASCII文字列 (大文字小文字区別なし): '$needleAscii' は '$haystackAscii' に {$countAsciiCaseInsensitive} 回出現します。\n\n"; // 出力: 2
26
27
28// --- 2. substr_countのマルチバイト文字列に対する動作 ---
29// substr_countはバイト単位で検索するため、マルチバイト文字(例: 日本語、絵文字)では
30// 予期せぬ結果になることがあります。
31$haystackMultiByte = "こんにちは、世界!こんにちは、PHP!";
32$needleMultiByte = "こんにちは"; // この文字列はUTF-8で5文字(15バイト)です。
33
34// substr_countは「こんにちは」というバイト列の出現回数をカウントします。
35// この例では、たまたま期待通りの結果(2回)となりますが、
36// 部分的なバイト列が別の文字と一致する場合など、常に文字単位で動作するわけではありません。
37$countMultiByteDirect = substr_count($haystackMultiByte, $needleMultiByte);
38echo "マルチバイト文字列 (substr_count): '$needleMultiByte' は '$haystackMultiByte' に {$countMultiByteDirect} 回出現します。\n\n"; // 出力: 2
39
40
41// --- 3. キーワード「mb_substr_count」への対応 (マルチバイト文字対応のカスタムカウント関数) ---
42// PHPには標準でmb_substr_count関数は存在しません。
43// 以下のカスタム関数は、マルチバイト文字列の文字単位での出現回数を正確にカウントします。
44// これは、mb_strpos() をループで利用して実現します。
45
46/**
47 * マルチバイト文字列における部分文字列の出現回数を文字単位でカウントします。
48 * PHPの標準substr_countがバイト単位でカウントするのに対し、この関数は文字単位でカウントします。
49 *
50 * @param string      $haystack 検索対象の文字列。
51 * @param string      $needle   検索する部分文字列。
52 * @param int         $offset   検索開始位置の文字オフセット。負の値は文字列の終わりからのオフセット。
53 * @param int|null    $length   検索する文字列の最大長(文字数)。nullの場合は文字列の最後まで。
54 * @param string|null $encoding 文字エンコーディング。nullの場合はmb_internal_encoding()を使用。
55 * @return int 出現回数。
56 */
57function mb_substr_count_char_aware(
58    string $haystack,
59    string $needle,
60    int $offset = 0,
61    ?int $length = null,
62    ?string $encoding = null
63): int {
64    // 空のneedleは無限にマッチするため、0を返します。
65    if ($needle === '') {
66        return 0;
67    }
68
69    // デフォルトエンコーディングを設定
70    $encoding = $encoding ?? mb_internal_encoding();
71
72    // offsetとlengthを文字単位で調整し、検索対象の文字列範囲を特定します。
73    $haystackLength = mb_strlen($haystack, $encoding);
74    if ($offset < 0) {
75        $offset = max(0, $haystackLength + $offset);
76    }
77    if ($length !== null) {
78        $length = max(0, min($length, $haystackLength - $offset));
79    } else {
80        $length = $haystackLength - $offset;
81    }
82
83    // 検索範囲を切り出し、この範囲内で部分文字列を検索します。
84    $searchString = mb_substr($haystack, $offset, $length, $encoding);
85
86    $count = 0;
87    $needleLength = mb_strlen($needle, $encoding);
88    $currentOffset = 0; // searchString内での現在の検索開始文字オフセット
89
90    // mb_strposを使って、見つかるたびにその次から検索を再開します。
91    while (($pos = mb_strpos($searchString, $needle, $currentOffset, $encoding)) !== false) {
92        $count++;
93        // 見つかった部分文字列の直後から次の検索を開始します(重複カウントなし)。
94        $currentOffset = $pos + $needleLength;
95    }
96
97    return $count;
98}
99
100// --- カスタム関数 mb_substr_count_char_aware の使用例 ---
101$haystackMultiByte = "こんにちは、世界!こんにちは、PHP!";
102$needleMultiByte = "こんにちは";
103$needleEmoji = "🍎"; // 絵文字もマルチバイト文字です
104
105// 文字単位で正確にカウント
106$countCharAware = mb_substr_count_char_aware($haystackMultiByte, $needleMultiByte);
107echo "マルチバイト文字列 (mb_substr_count_char_aware): '$needleMultiByte' は '$haystackMultiByte' に {$countCharAware} 回出現します。\n"; // 出力: 2
108
109$haystackWithEmoji = "🍎バナナ🍎りんご🍎みかん";
110$countEmoji = mb_substr_count_char_aware($hay haystackWithEmoji, $needleEmoji);
111echo "絵文字を含む文字列 (mb_substr_count_char_aware): '$needleEmoji' は '$haystackWithEmoji' に {$countEmoji} 回出現します。\n"; // 出力: 3
112
113// offsetとlengthを指定した使用例
114// 5文字目から検索を開始します(「こんにちは」の「は」の後から)。
115$countWithOffset = mb_substr_count_char_aware($haystackMultiByte, $needleMultiByte, 5);
116echo "マルチバイト文字列 (mb_substr_count_char_aware, offset=5): '$needleMultiByte' は '$haystackMultiByte' に {$countWithOffset} 回出現します。\n"; // 出力: 1
117?>

PHPのsubstr_count関数は、指定された文字列($haystack)の中に、特定の部分文字列($needle)が何回出現するかを数えるための関数です。検索を開始する位置を$offset、検索する最大長を$lengthで指定でき、見つかった回数を整数値(int)で返します。この関数は、デフォルトでは大文字・小文字を区別してカウントし、区別しない場合は検索対象と部分文字列を事前に小文字に変換する必要があります。

しかし、substr_countは文字列をバイト単位で処理するため、日本語や絵文字などのマルチバイト文字を含む文字列では、意図しない結果となることがあります。例えば「こんにちは」のような文字列の場合、バイト列として一致するかどうかで判断されるため、文字単位での正確なカウントは保証されません。

PHPには標準でmb_substr_countという関数は存在しません。そのため、マルチバイト文字列において文字単位で正確な出現回数を数えたい場合は、カスタム関数を自作する必要があります。サンプルコードで提供されているmb_substr_count_char_aware関数は、この目的のために設計されており、mb_strposなどのマルチバイト対応関数を組み合わせて文字単位でのカウントを実現しています。このカスタム関数を用いることで、日本語や絵文字を含む文字列でも、指定された部分文字列の出現回数を文字として正確に把握できます。マルチバイト関連関数を正しく機能させるため、mb_internal_encodingをUTF-8などに設定しておくことを推奨します。

substr_count関数は指定された部分文字列の出現回数をカウントしますが、デフォルトで大文字・小文字を区別します。大文字・小文字を区別しない場合は、mb_strtolower関数などで事前に文字列を変換してください。特に注意が必要なのは、この関数が文字列をバイト単位で検索する点です。日本語や絵文字などのマルチバイト文字列では、期待する文字単位でのカウントではなく、バイト列の一致を数えるため、意図しない結果となることがあります。PHPには標準のmb_substr_count関数は存在しません。マルチバイト文字列を文字単位で正確に数えたい場合は、サンプルコードに示されているようにmb_strposなどを利用したカスタム関数を実装する必要があります。また、mb_internal_encoding('UTF-8')などを用いて、PHPの内部文字エンコーディングを適切に設定することで、マルチバイト関連関数が正しく動作し、より安全にコードを利用できます。

PHP substr_countで大文字小文字を区別せずにカウントする

1<?php
2
3/**
4 * substr_count を使用して、文字列内の部分文字列の出現回数を大文字小文字を区別せずにカウントします。
5 *
6 * @param string $haystack 検索対象の文字列。
7 * @param string $needle 検索する部分文字列。
8 * @return int 部分文字列の出現回数。
9 */
10function countSubstrCaseInsensitive(string $haystack, string $needle): int
11{
12    // 検索対象の文字列と検索する部分文字列の両方を小文字に変換します。
13    // これにより、substr_count が大文字小文字を区別せずに検索を行うことができます。
14    $lowerHaystack = strtolower($haystack);
15    $lowerNeedle = strtolower($needle);
16
17    // 小文字に変換された文字列と部分文字列を使って、substr_count で出現回数をカウントします。
18    return substr_count($lowerHaystack, $lowerNeedle);
19}
20
21// --- 使用例 ---
22
23$text = "Hello World! PHP is great, and PHP 8 is even better. Long live PHP!";
24$searchText = "php";
25
26echo "元の文字列: " . $text . "\n";
27echo "検索する部分文字列 (大文字小文字を区別しない): '" . $searchText . "'\n";
28
29// countSubstrCaseInsensitive 関数を呼び出し、出現回数を取得します。
30$count = countSubstrCaseInsensitive($text, $searchText);
31
32echo "出現回数: " . $count . "\n"; // 期待される出力: 3 (PHP, PHP, PHP!)
33
34echo "\n--- 別の例 ---\n";
35
36$text2 = "Apple, apple, and APPLES.";
37$searchText2 = "APPLe";
38echo "元の文字列: " . $text2 . "\n";
39echo "検索する部分文字列 (大文字小文字を区別しない): '" . $searchText2 . "'\n";
40$count2 = countSubstrCaseInsensitive($text2, $searchText2);
41echo "出現回数: " . $count2 . "\n"; // 期待される出力: 3
42
43?>

PHPのsubstr_count関数は、指定した文字列($haystack)の中に、特定の部分文字列($needle)が何回出現するかを数え、その回数を整数(int)で返す関数です。この関数は引数として、検索対象の文字列と検索したい部分文字列を必須で受け取ります。オプションとして、検索を開始する位置($offset)や検索範囲の長さ($length)も指定できますが、デフォルトでは大文字と小文字を区別して検索を行います。

今回のサンプルコードでは、substr_count関数を利用して、部分文字列の出現回数を大文字小文字を区別せずにカウントする方法を示しています。countSubstrCaseInsensitiveという関数内で、まず検索対象の文字列$haystackと検索する部分文字列$needleの両方をstrtolower関数で小文字に変換しています。これにより、元の文字列中の「PHP」と検索文字列の「php」のように、大文字小文字の違いがある場合でも同じものとして認識されるようになります。その後、小文字に変換されたこれらの文字列をsubstr_count関数に渡すことで、大文字小文字を無視した出現回数を正確に取得できるようになります。

例えば、「Hello World! PHP is great, and PHP 8 is even better. Long live PHP!」という文字列から「php」を大文字小文字を区別せずに検索すると、結果として「PHP」が3回出現しているとカウントされます。このように、事前に文字列を小文字に統一する前処理を行うことで、より柔軟な文字列検索を実現できます。

substr_count関数は、デフォルトで大文字と小文字を区別して部分文字列の出現回数をカウントします。そのため、サンプルコードではstrtolower関数を用いて検索対象と検索する部分文字列の両方を事前に小文字に変換し、大文字小文字を区別しない検索を実現しています。この前処理を行わない場合、「PHP」と「php」は異なる文字列として扱われ、期待通りの結果が得られませんので注意が必要です。また、日本語のようなマルチバイト文字を扱う場合は、strtolowerの代わりにmb_strtolowerなどのマルチバイト対応関数を使用し、文字エンコーディングを考慮することが重要です。substr_countの第三引数$offsetや第四引数$lengthを指定すると、文字列の特定範囲内でのみ検索を行うことも可能です。

PHP substr_count関数で文字出現回数を数える

1<?php
2
3/**
4 * substr_count 関数の基本的な使い方を示すサンプルコードです。
5 * 指定された文字列 (haystack) の中に、特定の文字列 (needle) が何回出現するかを数えます。
6 * オプションで検索を開始する位置 (offset) や検索範囲の長さ (length) を指定できます。
7 */
8
9// 検索対象となる元の文字列
10$text = "PHP は素晴らしい言語です。PHP を学ぶことはとても楽しいです。PHP はウェブ開発に広く使われます。";
11
12// 検索したい文字列
13$searchWord = "PHP";
14
15// 1. 最も基本的な使い方: 文字列全体から特定の文字列の出現回数を数える
16$count1 = substr_count($text, $searchWord);
17echo "1. 文字列 '{$text}' 内に '{$searchWord}' は {$count1} 回出現します。\n";
18// 期待される出力: 3
19
20// 2. オフセットを指定して検索: 特定の位置から検索を開始する
21// ここではインデックス 15 ('素晴らしい言語です。PHP' の 'P' から) 以降で検索
22$offset = 15;
23$count2 = substr_count($text, $searchWord, $offset);
24echo "2. 文字列 '{$text}' のインデックス {$offset} 以降に '{$searchWord}' は {$count2} 回出現します。\n";
25// 期待される出力: 2 (最初の 'PHP' はスキップされるため)
26
27// 3. オフセットと長さを指定して検索: 特定の範囲内で検索する
28// インデックス 15 から長さ 30 の範囲で検索
29// '素晴らしい言語です。PHP を学ぶことはとても楽しいです。P'
30$offset = 15;
31$length = 30;
32$count3 = substr_count($text, $searchWord, $offset, $length);
33echo "3. 文字列 '{$text}' のインデックス {$offset} から長さ {$length} の範囲に '{$searchWord}' は {$count3} 回出現します。\n";
34// 期待される出力: 1 (2つ目の 'PHP' のみ含まれるため)
35
36// 4. 検索対象の文字列が見つからない場合
37$notFoundWord = "Python";
38$count4 = substr_count($text, $notFoundWord);
39echo "4. 文字列 '{$text}' 内に '{$notFoundWord}' は {$count4} 回出現します。\n";
40// 期待される出力: 0
41
42?>

PHPのsubstr_count関数は、指定した文字列($haystack)の中に、特定の文字列($needle)が何回出現するかを数えるための関数です。

第一引数$haystackには検索対象となる元の文字列を、第二引数$needleには検索したい文字列を渡します。オプションとして、第三引数$offsetで検索を開始する位置(文字列の先頭を0とするインデックス)を、第四引数$lengthで検索範囲の長さを指定できます。この関数は、$needleが見つかった回数を整数(int)で返します。

サンプルコードの最初の例では、文字列全体から"PHP"という単語が何回出現するかを数えており、結果は3となります。次に、$offsetに15を指定すると、文字列のインデックス15以降からのみ"PHP"を検索するため、最初の"PHP"は数えられず、結果として2が返されます。さらに、$offsetを15、$lengthを30と指定すると、インデックス15から30文字の範囲内でのみ検索が行われ、この範囲には2つ目の"PHP"が1回だけ含まれるため、結果は1となります。検索したい文字列が見つからない場合は、出現回数として0が返されることも確認できます。

このように、substr_count関数は、文字列内の特定の部分文字列の出現回数を効率的に調べ、必要に応じて検索範囲を細かく制御できる便利な機能です。

substr_count関数は、大文字と小文字を区別して部分文字列の出現回数を数えます。そのため、「PHP」と「php」は異なるものとして扱われます。検索文字列が空の場合、PHP 8以降では警告が出て0を返すため、常に適切な文字列を指定してください。オフセットや長さに負の値を指定することも可能ですが、挙動が直感的でない場合があるため注意が必要です。

この関数はバイト単位で処理を行います。日本語のようなマルチバイト文字を含む文字列では、文字数ではなくバイト数でオフセットや長さを指定することになり、期待通りの結果が得られないことがあります。マルチバイト文字を正確に数えたい場合は、mb_substr_count関数(mbstring拡張)の利用を検討してください。また、指定した検索範囲が文字列の長さを超えてもエラーにはなりませんが、結果が想定通りか確認することをお勧めします。

PHP substr_countで部分文字列を数える

1<?php
2
3/**
4 * PHPのsubstr_count関数を使用して、文字列内の部分文字列の出現回数を数える方法を示します。
5 * この関数は、大文字小文字を区別してカウントします。
6 *
7 * @param string $haystack 検索対象の文字列。
8 * @param string $needle 検索する部分文字列。
9 */
10function demonstrateSubstrCount(string $haystack, string $needle): void
11{
12    echo "元の文字列: \"{$haystack}\"\n";
13    echo "検索する部分文字列: \"{$needle}\"\n\n";
14
15    // 1. 基本的な使い方: 全ての文字列から部分文字列の出現回数を数える
16    // 例: "banana" は "banana is a banana." に2回出現する
17    $countAll = substr_count($haystack, $needle);
18    echo "1. 全体からの出現回数: {$countAll} 回\n";
19
20    // 2. オフセットを指定した使い方: 指定した位置から検索を開始する
21    // 例: 10文字目から検索 (" is a banana." に "banana" は1回出現)
22    $offset = 10;
23    $countFromOffset = substr_count($haystack, $needle, $offset);
24    echo "2. {$offset}文字目から検索した出現回数: {$countFromOffset} 回\n";
25
26    // 3. 長さを指定した使い方: 指定した長さの範囲内でのみ検索する
27    // 例: 0文字目から15文字の範囲で検索 ("banana is a fru" に "banana" は1回出現)
28    $length = 15;
29    $countWithLength = substr_count($haystack, $needle, 0, $length);
30    echo "3. 0文字目から{$length}文字の範囲で検索した出現回数: {$countWithLength} 回\n";
31
32    // 4. オフセットと長さを両方指定した使い方: 指定した範囲内でのみ検索する
33    // 例: 7文字目から10文字の範囲で検索 (範囲: " is a ") に "banana" は0回出現)
34    $offsetCombined = 7;
35    $lengthCombined = 10;
36    $countCombined = substr_count($haystack, $needle, $offsetCombined, $lengthCombined);
37    echo "4. {$offsetCombined}文字目から{$lengthCombined}文字の範囲で検索した出現回数: {$countCombined} 回\n";
38}
39
40// サンプルコードの実行
41$text = "banana is a fruit, a yellow banana. Another banana.";
42$searchWord = "banana";
43demonstrateSubstrCount($text, $searchWord);
44
45echo "\n--- 大文字小文字を区別する場合の例 ---\n";
46$textCase = "PHP is a scripting language. Php is widely used.";
47$searchWordCase = "PHP";
48demonstrateSubstrCount($textCase, $searchWordCase); // PHPは1回カウント
49
50echo "\n--- 大文字小文字を区別しない場合の対応 (substr_countでは直接不可) ---\n";
51// substr_count自体は大文字小文字を区別します。
52// 大文字小文字を区別せずに数えるには、検索前に両方の文字列を同じケースに変換する必要があります。
53$textCaseInsensitive = "PHP is a scripting language. Php is widely used.";
54$searchWordCaseInsensitive = "php";
55
56// 全てを小文字に変換して数える
57$lowercaseText = strtolower($textCaseInsensitive);
58$lowercaseSearchWord = strtolower($searchWordCaseInsensitive);
59$countCaseInsensitive = substr_count($lowercaseText, $lowercaseSearchWord);
60
61echo "元の文字列 (大文字小文字混在): \"{$textCaseInsensitive}\"\n";
62echo "検索する部分文字列 (小文字): \"{$searchWordCaseInsensitive}\"\n";
63echo "大文字小文字を区別せずにカウントした場合: {$countCaseInsensitive} 回\n"; // 2回

PHPのsubstr_count関数は、指定した文字列($haystack)の中に、特定の部分文字列($needle)が何回出現するかを数えるための関数です。戻り値は出現回数を表す整数(int)となります。この関数は、大文字と小文字を厳密に区別してカウントします。

引数$offsetを指定すると、文字列の先頭からではなく、指定した位置から検索を開始できます。さらに$lengthを指定すると、$offsetから$lengthの範囲内でのみ検索を実行することが可能です。

サンプルコードでは、"banana"という部分文字列が、"banana is a fruit, a yellow banana. Another banana."という文字列に何回出現するかを様々なパターンで数えています。基本的な使い方では文字列全体を検索し、$offset$lengthを指定することで、検索を開始する位置や検索する範囲を限定できることを示しています。例えば、$offset10に指定すると10文字目以降から検索し、$length15に指定すると先頭から15文字の範囲で検索が行われます。

substr_count関数は大文字小文字を区別するため、例えば"PHP""php"は異なるものとして扱われます。大文字小文字を区別せずにカウントしたい場合は、検索対象の文字列と検索する部分文字列の両方を、strtolower()などの関数で事前に小文字に変換するなどの対応が必要です。

PHPのsubstr_count関数は、文字列内で指定した部分文字列が何回出現するかを数える際に使用します。この関数は、大文字小文字を厳密に区別する点に特に注意が必要です。もし大文字小文字を区別せずにカウントしたい場合は、検索対象の文字列と検索する部分文字列の両方を、事前にstrtolower関数などで小文字に変換してから利用してください。

また、引数として$offsetを指定すると検索開始位置を、$lengthを指定すると検索範囲の長さをそれぞれ設定できます。これにより、文字列の特定の部分でのみ出現回数を数えることが可能です。これらの引数を誤って指定すると、意図しない検索結果になるため、指定する数値が文字列の範囲内で正しい意味を持つか、十分確認することが重要です。適切な引数設定で、正確な文字列処理を実現しましょう。

関連コンテンツ

関連プログラミング言語