【PHP8.x】strtok()関数の使い方
strtok関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
strtok関数は、指定された文字列を特定の区切り文字で分割し、その部分文字列(トークン)を順次取得する関数です。この関数は、ある文字列の中から意味のある単語やフレーズを抽出する際に役立ちます。
最初の呼び出しでは、分割したい元の文字列と、区切り文字として使用する文字を指定します。区切り文字は1文字だけでなく、複数の文字を組み合わせて指定することも可能です。例えば、「,」「;」「.」といった複数の文字を区切り文字として一度に指定できます。この最初の呼び出しによって、関数は内部で現在の処理位置を記憶します。
2回目以降のstrtok関数の呼び出しでは、元の文字列を再度指定する必要はなく、区切り文字のみを指定します。これにより、関数は前回の処理位置から残りの文字列を分割し、次のトークンを返します。すべての部分文字列が取得され、それ以上分割できる部分がなくなった場合、この関数はfalseを返します。
この関数は元の文字列を直接変更することはありません。また、連続する区切り文字は1つの区切り文字として扱われるため、例えば「word,,next」という文字列を「,」で分割した場合、「word」と「next」の間に空のトークンは生成されません。日本語のようなマルチバイト文字を含む文字列を扱う場合は、期待通りの動作をしないことがあるため、mb_strtokのようなマルチバイトセーフな関数を使用することを推奨します。
構文(syntax)
1<?php 2$string = "apple,banana,orange"; 3$token = strtok($string, ","); // 最初のトークンを取得 4 5while ($token !== false) { 6 echo $token . PHP_EOL; 7 $token = strtok(","); // 次のトークンを取得 8} 9?>
引数(parameters)
string $string, string $token
- string $string: 分割したい元の文字列
- string $token: 区切り文字として使用する文字列
戻り値(return)
string|false
指定された文字列 $str を、区切り文字 $token によって分割し、分割された文字列の次の部分を返します。 区切り文字が見つからない場合、または文字列の終わりに達した場合は false を返します。
サンプルコード
PHP strtokで文字列を分割する
1<?php 2 3/** 4 * strtok関数を使用して文字列を区切り文字で分割し、 5 * 各トークンを出力する例を示します。 6 * システムエンジニアを目指す初心者の方にも理解しやすいよう、 7 * 分割処理の基本的な流れを追って解説します。 8 */ 9function demonstrateStrtok(): void 10{ 11 // 分割したい元の文字列を定義します。 12 // ここでは、カンマ、セミコロン、ピリオドが区切り文字として使われています。 13 $sourceString = "Apple,Banana;Orange.Grape"; 14 15 // 文字列を分割するための区切り文字(トークン)を定義します。 16 // 複数の区切り文字をまとめて指定できます。 17 $delimiters = ",;."; 18 19 echo "元の文字列: " . $sourceString . PHP_EOL; 20 echo "使用する区切り文字: '" . $delimiters . "'" . PHP_EOL . PHP_EOL; 21 echo "--- 分割されたトークン ---" . PHP_EOL; 22 23 // strtok関数を初めて呼び出す際は、元の文字列と区切り文字の両方を指定します。 24 // これにより、strtokは元の文字列の最初の部分(トークン)を返します。 25 // 以降の呼び出しのために、strtokは内部的に元の文字列の状態を記憶します。 26 $token = strtok($sourceString, $delimiters); 27 28 // strtokがfalseを返すまで(つまり、すべてのトークンが取得されるまで)ループを続けます。 29 // falseは、残りのトークンがないことを意味します。 30 while ($token !== false) { 31 echo "取得したトークン: " . $token . PHP_EOL; 32 33 // 2回目以降のstrtokの呼び出しでは、区切り文字のみを指定します。 34 // strtokは前回の呼び出しで記憶した元の文字列から次のトークンを探します。 35 $token = strtok($delimiters); 36 } 37 echo "------------------------" . PHP_EOL; 38} 39 40// 上記の関数を実行して、strtokの動作を確認します。 41demonstrateStrtok(); 42
PHPのstrtok関数は、指定された文字列を特定の区切り文字で分割し、その一部を順次取得するために使用されます。システムエンジニアを目指す初心者の方にとって、文字列処理の基本を理解する上で役立つ関数です。
この関数は、string $stringとstring $tokenという2つの引数を受け取ります。$stringは分割したい元の文字列を指定し、$tokenは文字列を区切りたい一つまたは複数の区切り文字を指定します。戻り値は、分割された文字列の一部(トークン)が文字列として返されます。しかし、これ以上分割する部分がない場合はfalseを返します。
サンプルコードでは、"Apple,Banana;Orange.Grape"という元の文字列を、カンマ、セミコロン、ピリオドを区切り文字として分割しています。strtokを最初に呼び出す際には、元の文字列$sourceStringと区切り文字$delimitersの両方を指定します。これにより、最初のトークン"Apple"が取得され、strtokは内部的に現在の処理位置を記憶します。2回目以降の呼び出しでは、区切り文字$delimitersのみを指定することで、記憶された位置から次のトークン("Banana"、"Orange"、"Grape"など)を順に探し出し、取得します。
すべてのトークンが取得され、これ以上分割する部分がなくなると、strtokはfalseを返します。サンプルコードでは、strtokがfalseを返すまでwhileループを継続し、これにより元の文字列のすべてのトークンを順番に処理しています。このようにstrtokを使うと、文字列を効率的に分割して、各部分を簡単に取り出すことが可能です。
strtok関数は、一度元の文字列と区切り文字を指定すると、その後の呼び出しでは区切り文字のみで次の部分(トークン)を順に取得する特殊な動作をします。これは、関数が内部で現在の処理位置を記憶しているためです。そのため、複数の異なる文字列を同時にstrtokで分割しようとすると、意図しない結果になる可能性があります。分割処理は一つの文字列に対して完結させてください。
トークンがもうない場合や、初回呼び出しで元の文字列が空の場合はfalseを返します。ループでトークンを取得する際は、厳密に!== falseで判定することが重要です。また、連続する区切り文字はスキップされ、空のトークンは生成されない点も理解しておきましょう。用途に応じてexplodeなどの他の文字列分割関数も検討してください。
PHP strtokで最後のトークンを取得する
1<?php 2 3/** 4 * 文字列から指定されたデリミタで区切られた最後のトークンを取得します。 5 * 6 * strtok() 関数は内部状態を持つため、この関数は連続する strtok() 呼び出しを管理します。 7 * 複数のデリミタが連続する場合、strtokはそれらを単一のデリミタとして扱います。 8 * 空文字列やトークンが見つからない場合はnullを返します。 9 * 10 * @param string $string 処理する元の文字列。 11 * @param string $token デリミタとして使用する文字のリスト。例: "," や ".-" など。 12 * @return string|null 最後のトークンが見つかった場合はその文字列、 13 * トークンが見つからなかった場合は null を返します。 14 */ 15function getLastToken(string $string, string $token): ?string 16{ 17 $lastToken = null; // 最後のトークンを保持する変数。初期値はnull。 18 19 // strtokの最初の呼び出しで、対象の文字列とデリミタを指定する。 20 // これにより、strtokは内部的に文字列の状態を記憶する。 21 $current = strtok($string, $token); 22 23 // strtokがfalseを返すまで(つまり、トークンがなくなるまで)ループを続ける。 24 while ($current !== false) { 25 $lastToken = $current; // 現在のトークンを$lastTokenに記録する。 26 // 次のトークンを取得するために、strtokにデリミタのみを渡す。 27 // strtokは内部的に記憶している文字列の残りの部分から処理を続ける。 28 $current = strtok($token); 29 } 30 31 return $lastToken; // 最後に記録されたトークン、またはnullを返す。 32} 33 34// --- 使用例 --- 35$testCases = [ 36 ["apple,banana,cherry,date", ",", "date"], // 通常のケース 37 ["one..two...three", ".", "three"], // デリミタが連続する場合 38 ["", ",", null], // 空文字列 39 [",,,", ",", null], // デリミタのみの文字列 40 ["HelloWorld", ",", "HelloWorld"], // デリミタが含まれない文字列 41 ["first-second.third", ".-", "third"], // 複数のデリミタ文字 42]; 43 44foreach ($testCases as [$str, $delim, $expected]) { 45 $result = getLastToken($str, $delim); 46 $output = sprintf( 47 "Original: '%s', Delimiter: '%s', Result: '%s' (Expected: '%s') %s\n", 48 $str, 49 $delim, 50 $result ?? 'null', // nullの場合は'null'と表示 51 $expected ?? 'null', // nullの場合は'null'と表示 52 ($result === $expected) ? "(OK)" : "(NG)" 53 ); 54 echo $output; 55}
PHPのstrtok関数は、文字列を指定した区切り文字(デリミタ)で分割し、その一部を順に取り出す機能を提供します。この関数には「内部状態」という特徴があり、最初の呼び出しで対象の文字列とデリミタを指定すると、2回目以降はデリミタのみを渡すことで、前回処理した箇所の続きからトークンを取得し続けます。
サンプルコードのgetLastToken関数は、このstrtok関数の特性を利用し、与えられた文字列からデリミタで区切られた「最後の部分(トークン)」を効率的に取得するためのものです。
この関数は、引数として処理したい元の文字列$stringと、区切り文字となる$token(例: ,や.-など、複数の文字を指定可能)を受け取ります。内部ではstrtokを繰り返し呼び出し、取得できたトークンを$lastTokenという変数に順次上書きしていきます。strtokがこれ以上トークンを見つけられずfalseを返すとループが終了し、その時点で$lastTokenに記録されている文字列、つまり最後のトークンが返されます。もし、元の文字列が空だったり、デリミタのみでトークンが見つからなかった場合はnullを返します。これにより、複雑な文字列分割の処理を簡潔に実装できます。
strtok関数は、最初に指定された文字列の処理状況を内部で記憶する特性があります。そのため、同じ処理フロー内で異なる文字列を同時にstrtokで解析しようとすると、期待しない結果となる可能性がありますので注意が必要です。この内部状態はグローバルに扱われるため、アプリケーション全体でstrtokの利用状況を把握しておくことが重要です。また、連続する複数のデリミタは一つとして扱われ、空のトークンは生成されません。全てのトークンを処理し終えるか、指定されたトークンが見つからない場合はfalseを返しますので、その戻り値のチェックを適切に行ってください。サンプルコードのように、falseをnullに変換して扱うことで、一貫した処理がしやすくなります。
PHP strtokで文字列トークンを反転する
1<?php 2 3/** 4 * strtok 関数を使用して文字列内のトークンの順序を逆転させます。 5 * 6 * strtok は、連続するデリミタや文字列の先頭・末尾のデリミタを 7 * 特別な方法で処理します。例えば、"a b" を " " で分割すると、 8 * "a"、"" (空文字列)、"b" の3つのトークンが生成されます。 9 * この関数では、これらの空文字列のトークンもそのまま保持し、 10 * その順序を逆転させて再結合します。 11 * 12 * @param string $string 処理対象の文字列。 13 * @param string $delimiter トークンを区切る文字。単一の文字でも複数の文字でも可。 14 * 複数の文字の場合、それらの文字のいずれかがデリミタとして機能します。 15 * @return string トークンの順序が逆転した新しい文字列。 16 */ 17function reverseStringTokens(string $string, string $delimiter = ' '): string 18{ 19 // トークンを格納するための配列を初期化します。 20 $tokens = []; 21 22 // strtok は内部状態を持つため、最初の呼び出しで処理対象の文字列とデリミタを設定します。 23 // 以降のトークンを取得する際は、第一引数に null を渡します。 24 $token = strtok($string, $delimiter); 25 26 // false が返されるまで、文字列からトークンを一つずつ取り出し、配列に追加します。 27 // strtok はトークンが見つからない場合に false を返します。 28 while ($token !== false) { 29 $tokens[] = $token; 30 // 次のトークンを取得するために、第一引数に null を渡します。 31 $token = strtok(null, $delimiter); 32 } 33 34 // 収集したトークンの配列の順序を逆転させます。 35 $reversedTokens = array_reverse($tokens); 36 37 // 逆順になったトークンを元のデリミタで結合し、一つの文字列に戻します。 38 return implode($delimiter, $reversedTokens); 39}
このサンプルコードは、PHPのstrtok関数を利用して、指定された文字列内のトークンの順序を逆転させる方法を示すものです。reverseStringTokens関数は、文字列を特定のデリミタで分割し、得られたトークンを逆順に並べ替えてから、再度デリミタで結合して新しい文字列を生成します。
strtok関数は、文字列からトークンを一つずつ取り出すための関数で、内部で処理中の文字列の状態を保持します。そのため、最初の呼び出しでは対象の文字列とデリミタを引数に指定し、二回目以降のトークン取得時には第一引数にnullを渡します。この関数は、連続するデリミタや文字列の先頭・末尾にあるデリミタによって生成される空のトークンもそのまま保持するという特徴があります。例えば、「a b」をスペースで分割した場合、「a」、「」(空文字列)、「b」という3つのトークンが抽出されます。
reverseStringTokens関数では、まずstrtokを使用して文字列からすべてのトークンを抽出し、それらを配列に順次格納します。strtokがトークンを見つけられずにfalseを返すと抽出を終了します。次に、array_reverse関数を使ってこのトークン配列の要素の順序を逆転させます。最後に、implode関数で、逆順になったトークンを元のデリミタで結合し、最終的な文字列として返します。引数$stringは処理対象の文字列、$delimiterはトークンを区切る文字を指定し、戻り値はトークンの順序が逆転した新しい文字列となります。
strtok関数は、最初の呼び出しで処理対象文字列とデリミタを設定しますが、以降のトークン取得時には第一引数にnullを渡して内部状態を引き継ぐ特殊な関数であることに注意が必要です。他の文字列分割関数とは異なる挙動のため、慣れるまで注意して利用してください。トークンが見つからない場合はfalseを返すため、while ($token !== false)のように戻り値を厳密にチェックして利用することが重要です。
また、連続するデリミタや文字列の先頭・末尾にデリミタがある場合、空文字列のトークンが生成されることがあります。このサンプルコードでは空文字列も保持し、その順序を逆転させていますが、処理結果が意図と異なる場合は、生成されたトークンの中から空文字列を除外する追加処理を検討すると良いでしょう。第二引数のデリミタは文字列で指定しますが、その中の文字のいずれかがデリミタとして機能します。
PHP strtok と explode 比較処理
1<?php 2 3/** 4 * strtok() と explode() の動作の違いを示すサンプルコード。 5 * 6 * strtok() は文字列をトークンで分割し、呼び出しごとに1つのトークンを返します。 7 * 初回は分割対象文字列とトークンを渡し、2回目以降は対象文字列に null を渡します。 8 * 9 * explode() は文字列をデリミタで分割し、結果を一度に配列で返します。 10 * これは、文字列全体を一度に分割し、結果を配列として受け取りたい場合に適しています。 11 */ 12 13// 比較対象となる文字列 14$text = "one;two;three;four"; 15// 区切り文字(トークンまたはデリミタ) 16$delimiter = ";"; 17 18echo "--- explode() の使用例 ---" . PHP_EOL; 19// explode() は文字列をデリミタで分割し、結果を配列で一度に返します。 20// 関数から返されるのは分割された部分文字列の配列です。 21$partsArray = explode($delimiter, $text); 22echo "explode() の結果 (配列): "; 23print_r($partsArray); 24echo PHP_EOL; 25 26echo "--- strtok() の使用例 ---" . PHP_EOL; 27// strtok() は文字列をトークンで分割し、呼び出しごとに1つのトークンを返します。 28// 初回呼び出し時に、分割したい元の文字列と区切り文字(トークン)を渡します。 29$token = strtok($text, $delimiter); 30 31$count = 0; 32while ($token !== false) { 33 echo "strtok() トークン " . (++$count) . ": " . $token . PHP_EOL; 34 // 2回目以降の呼び出しでは、最初の引数に null を渡します。 35 // strtok() は内部で保持している元の文字列から次のトークンを抽出します。 36 // トークンがこれ以上ない場合、false を返します。 37 $token = strtok(null, $delimiter); 38} 39 40?>
このサンプルコードは、PHP 8におけるstrtok()関数とexplode()関数の、文字列を分割する際の動作の違いを具体的に示しています。
explode()関数は、指定されたデリミタ(区切り文字)で文字列全体を一度に分割し、その結果を部分文字列の配列として返します。引数には分割したい文字列と区切り文字を渡し、戻り値は分割された部分文字列の配列です。サンプルコードでは、"one;two;three;four"という文字列を;で分割し、結果としてarray('one', 'two', 'three', 'four')という配列が得られる様子が確認できます。
一方、strtok()関数は、文字列をトークン(区切り文字)で分割しますが、explode()とは異なり、呼び出しごとに1つのトークンを順次返します。最初の呼び出しでは、分割したい元の文字列と区切り文字を引数に渡します。strtok()は、その文字列の先頭から最初のトークンを見つけて返します。2回目以降の呼び出しでは、最初の引数にnullを渡すことで、strtok()が内部で記憶している元の文字列から次のトークンを抽出し続けます。戻り値は次のトークン文字列で、これ以上トークンがない場合はfalseを返します。サンプルコードではwhileループを使い、strtok(null, $delimiter)を繰り返し呼び出してトークンを1つずつ取得する手順が示されています。
このように、explode()は文字列全体を一度に配列として取得したい場合に適しており、strtok()はメモリ効率や処理効率を考慮し、文字列からトークンを順次処理したい場合に有用です。
explode()は文字列全体を一度に分割し、結果を配列として受け取りたい場合に利用します。シンプルで直感的に扱えるのが特徴です。一方、strtok()は文字列を分割する際、呼び出しごとにトークンを一つずつ取り出す点で大きく異なります。
strtok()を初めて呼び出す際は、分割対象の文字列と区切り文字を両方渡しますが、2回目以降の呼び出しでは最初の引数にnullを渡す必要があります。これは、strtok()が内部で処理中の文字列の状態を記憶しているためです。すべてのトークンを取り終えるとfalseを返すため、ループで処理する場合は、この戻り値を適切にチェックすることが重要です。
これら二つの関数は、状況や目的によって使い分けが求められます。文字列を配列としてまとめて取得したい場合はexplode()を、大きな文字列を少しずつ処理したい場合や、メモリ使用量を抑えたい場合にstrtok()を選ぶと良いでしょう。