strtok()
Функция strtok() в PHP разбивает строку на части — токены. Узнайте синтаксис, внутренний указатель и отличия от explode().
Введение
Функция strtok() в PHP разбивает строку на небольшие фрагменты, называемые токенами. Токен — это часть текста между разделителями — отдельными символами (например, пробелом, запятой или символом новой строки), которые обозначают границу между частями.
Особенность strtok() заключается в её состоянии: функция запоминает текущую позицию в строке между вызовами. Первый вызов возвращает первый токен, каждый последующий вызов возвращает следующий токен, и так до исчерпания строки. На этой странице рассматривается синтаксис, принцип работы внутреннего указателя, распространённые ловушки и ситуации, когда лучше использовать explode().
Синтаксис
strtok(string $string, string $delimiter): string|false
// continuation call:
strtok(string $delimiter): string|falseСуществует два варианта вызова:
| Форма | Назначение |
|---|---|
strtok($string, $delimiter) | Начать токенизацию $string, вернуть первый токен. |
strtok($delimiter) | Продолжить с места предыдущего вызова, вернуть следующий токен. |
Важные детали параметров:
$delimiter— это набор символов, а не многосимвольный разделитель." !?"означает «разбивать по пробелу, восклицательному знаку или вопросительному знаку» — каждый символ является самостоятельным разделителем. Функция не разбивает по трёхсимвольной строке" !?"как целому.- Разделитель можно менять между вызовами, что является главным преимуществом
strtok()передexplode(). - Функция возвращает
false, когда токены заканчиваются (или если$delimiterпуст), поэтому её можно использовать как условие цикла.
В PHP 8.1+ старая форма продолжения
strtok(null, $delimiter)устарела. Для продолжения используйте одноаргументную формуstrtok($delimiter).
Базовый пример: перебор токенов в цикле
Типичный шаблон: один вызов для запуска, затем цикл while, который продолжает извлекать токены до тех пор, пока strtok() не вернёт false:
<?php
$string = "Hello World! How are you?";
$delimiter = " !?";
$token = strtok($string, $delimiter); // first token
while ($token !== false) {
echo $token . "\n";
$token = strtok($delimiter); // next token (single-arg form)
}Вывод:
Hello
World
How
are
youИспользуйте строгое сравнение !== false, а не просто while ($token). Токен "0" является ложным значением в PHP, поэтому нестрогая проверка может преждевременно прервать цикл при работе с реальными данными.
Последовательные разделители пропускаются
В отличие от explode(), функция strtok() рассматривает последовательность символов-разделителей как единый разделитель и никогда не возвращает пустые токены:
<?php
$tok = strtok("a,,b", ",");
while ($tok !== false) {
echo "[$tok]\n";
$tok = strtok(",");
}Вывод:
[a]
[b]Пустой фрагмент между двумя запятыми молча отбрасывается. explode(",", "a,,b") вернул бы ["a", "", "b"]. Если важно сохранять пустые поля (например, при работе с CSV), не используйте strtok().
Смена разделителя в процессе разбора
Поскольку внутренний указатель сохраняется, можно менять разделители между вызовами — это удобно при разборе данных вида key=value:
<?php
$line = "name=John; age=30";
$key = strtok($line, "="); // split on "=" → "name"
$value = strtok(";"); // now split on ";" → " John"
echo trim($key) . "\n";
echo trim($value) . "\n";Вывод:
name
JohnПолучение только первой строки
Быстрый способ прочитать только первую строку многострочной строки, не создавая массива из всех строк:
<?php
$text = "first line\nsecond line\nthird line";
$firstLine = strtok($text, "\n");
echo $firstLine . "\n";Вывод:
first linestrtok() и explode()
Обе функции разбивают строки, но ведут себя по-разному:
strtok() | explode() | |
|---|---|---|
| Возвращает | один токен за вызов | сразу весь массив |
| Разделитель | набор одиночных символов | одна фиксированная многосимвольная строка |
| Пустые поля | пропускаются | сохраняются |
| Состояние | с состоянием (внутренний указатель) | без состояния |
В большинстве современного кода explode() проще понять и она хорошо сочетается с функциями для работы с массивами. Используйте strtok(), когда нужно ленивое, пошаговое чтение токенов или требуется менять разделитель в процессе работы. Для разбора данных, разделённых запятыми с экранированием, предпочтите str_getcsv().
Распространённые ловушки
- Внутренний указатель является глобальным для строки. Если другая функция, использующая
strtok(), вызывается внутри вашего цикла, она нарушит текущую позицию. Завершайте одну токенизацию перед началом другой. - Не передавайте исходную строку повторно при продолжении.
strtok($string, $delimiter)перезапускает разбор с самого начала при каждом вызове. Продолжение должно использовать одноаргументную форму. - Пустые поля исчезают. Как показано выше,
strtok()не сообщает о том, что поле было пустым.
Заключение
strtok() обходит строку по одному токену за раз, разбивая по любому символу из набора разделителей и сохраняя внутренний указатель между вызовами. Наличие состояния делает её идеальной для ленивого разбора и смены разделителя в процессе работы, тогда как отбрасывание пустых полей делает её непригодной для данных с фиксированными столбцами. Когда нужно просто получить все части в виде массива, explode() обычно является более понятным выбором; для разбивки на фрагменты фиксированной длины см. str_split().