Извлечение цифр из строки в PHP: лучшие практики

Раздел: Основы PHP -> Обработка строк

Как оставить только цифры в строке: основные методы и их особенности

При обработке строк в PHP часто возникает необходимость извлечь только цифровые символы, отбросив всё остальное. Это может потребоваться при очистке телефонных номеров, идентификаторов, ввода форм или парсинге данных. Рассмотрим несколько решений - от самого эффективного до альтернативных подходов, с примерами и анализом возможных проблем.

Как быстро удалить все нецифровые символы из строки с помощью регулярного выражения?

Наиболее производительный и короткий способ - функция preg_replace. Она заменяет все символы, не являющиеся десятичными цифрами (0–9), на пустую строку. Для этого используется класс символов \D (все, кроме цифр) или инвертированный класс [^0-9].


$original = "Телефон: +7 (123) 456-78-90";
$digits_only = preg_replace('/\D/', '', $original);
echo $digits_only;
  
71234567890
  

Это решение подходит для любых строк, включая кириллицу, пробелы, знаки препинания. Цель: получить сплошную последовательность цифр независимо от формата исходных данных.

Возможные проблемы и типичные ошибки:
  • Если строка не содержит цифр, результатом будет пустая строка. Это нормально, но иногда может ввести в заблуждение при дальнейшей проверке.
  • Регулярное выражение без модификатора u работает только с однобайтовыми кодировками. Если строка в UTF-8 и содержит не-ASCII символы (например, буквы «ё»), проблем не возникает, так как \D удаляет любые нецифровые байты. Однако при работе с многобайтовыми символами, которые могут быть ошибочно восприняты, стоит добавить модификатор u: preg_replace('/\D/u', '', $string).
  • Не учитываются цифры, находящиеся в других системах счисления (например, арабо-индийские). Если нужны только арабские цифры (0–9), этот метод корректен.

Как очистить строку через фильтр FILTER_SANITIZE_NUMBER_INT?

PHP предоставляет встроенные фильтры для очистки данных. FILTER_SANITIZE_NUMBER_INT удаляет все символы, кроме цифр, а также знаков плюс (+) и минус (-). Если требуется оставить только цифры, после фильтрации нужно дополнительно убрать знаки.


$dirty = "Цена: -1 234 руб.";
$filtered = filter_var($dirty, FILTER_SANITIZE_NUMBER_INT);
echo $filtered;
  
-1234
  

Чтобы оставить только цифры, удаляем знаки:
$digits = str_replace(['+', '-'], '', $filtered);

Цель: быстро извлечь число со знаком, а затем при необходимости отбросить знак.

Типичные ошибки:
  • Фильтр не удаляет знак минус, если он стоит не на первой позиции (например, в середине строки). В итоге могут появиться лишние дефисы.
  • При отсутствии цифр фильтр вернет пустую строку.

Как извлечь цифры, перебирая строку посимвольно?

Классический ручной подход: проход по каждому символу и проверка с помощью ctype_digit.


$str = "Код ошибки: 404";
$result = '';
for ($i = 0; $i < strlen($str); $i++) {
    if (ctype_digit($str[$i])) {
        $result .= $str[$i];
    }
}
echo $result;
  
404
  

Цель: когда требуется полный контроль над процессом (например, одновременная запись позиций цифр) или нежелательны регулярные выражения.

Недостатки:
  • Медленнее регулярных выражений на длинных строках.
  • Не работает с многобайтовыми кодировками, так как $str[$i] обращается к байту, а не к символу. Используйте mb_strlen и mb_substr для UTF-8.

Как собрать цифры с помощью preg_match_all и implode?

Если нужно не удалить нецифровые символы, а именно найти все цифры и объединить их, можно использовать preg_match_all с шаблоном \d и соединить результат.


$text = "a1b2c3";
preg_match_all('/\d/', $text, $matches);
$digits = implode('', $matches[0]);
echo $digits;
  
123
  

Цель: получить массив найденных цифр для дальнейшей обработки (например, подсчета количества).

Особенность: если в строке нет цифр, $matches[0] будет пустым массивом, и implode вернет пустую строку. Ошибок не возникает, но результат может быть неожиданным, если ожидается число.

Как использовать str_replace для удаления известных нецифровых символов?

Если набор символов, которые нужно удалить, ограничен (например, только пробелы и дефисы), можно применить str_replace.


$phone = "+7-912-345-67-89";
$cleaned = str_replace(['+', '-', ' ', '(', ')'], '', $phone);
echo $cleaned;
  
79123456789
  

Цель: быстро очистить строку, когда известен точный перечень «мусорных» символов. Не подходит для неизвестных или переменных форматов.

Недостатки:
  • Если появятся новые нецифровые символы (например, буквы), они останутся.
  • Неэффективно при большом количестве заменяемых символов.

Как извлечь только цифры с помощью intval и floatval?

Эти функции преобразуют строку в число, отбрасывая все нецифровые символы, начиная с первого нецифрового. Однако результат может отличаться от ожидаемого, если цифры идут не с начала.


$str = "abc123def";
echo intval($str);  // 0
$str2 = "123abc";
echo intval($str2); // 123
  

Цель: получить целое или вещественное число из строки, которая начинается с цифр. Не подходит для извлечения всех цифр, расположенных в середине или конце.

Ограничение: intval и floatval останавливаются на первом нецифровом символе после цифр, а также игнорируют цифры после букв. Для полного извлечения всех цифр этот метод неприменим.
Пример

<?php
// 1. Удаление всех нецифровых символов с учётом Unicode
$str_unicode = "Ваш заказ № 42 – 1000 руб.";
$digits_unicode = preg_replace('/[^0-9]/u', '', $str_unicode);
echo "Unicode: $digits_unicode\n";

// 2. Извлечение цифр из строки с несколькими числами (с сохранением порядка)
$mixed = "item_12, price_34, qty_56";
$only_digits = preg_replace('/\D/', '', $mixed);
echo "Mixed: $only_digits\n";

// 3. Работа с пустой строкой
$empty_input = "Нет цифр";
$result_empty = preg_replace('/\D/', '', $empty_input);
echo "Empty result: '{$result_empty}' (длина " . strlen($result_empty) . ")\n";

// 4. Фильтрация с помощью filter_var и удаление знаков
$signed = "Температура: -15°C";
$sanitized = filter_var($signed, FILTER_SANITIZE_NUMBER_INT);
$digits_only_signed = str_replace(['-', '+'], '', $sanitized);
echo "From signed: $digits_only_signed\n";

// 5. Посимвольный обход с ctype_digit (однобайтовая строка)
$str_loop = "Осталось 7 дней";
$res = '';
for ($i = 0; $i < strlen($str_loop); $i++) {
    if (ctype_digit($str_loop[$i])) {
        $res .= $str_loop[$i];
    }
}
echo "Loop result: $res\n";

// 6. Использование preg_match_all для получения массива цифр
$source = "Код: 007, Пин: 1234";
preg_match_all('/\d/', $source, $matches);
$joined = implode('', $matches[0]);
echo "From matches: $joined\n";

// 7. str_replace для известных разделителей
$phone_s = "+1 (800) 555-01-02";
$phone_clean = str_replace(['+','-','(',')',' '], '', $phone_s);
echo "Phone: $phone_clean\n";

// 8. Использование intval (не рекомендуется для извлечения всех цифр)
$test_intval = "2019 год";
echo "intval: " . intval($test_intval) . "\n";  // 2019
$test_intval2 = "год 2019";
echo "intval2: " . intval($test_intval2) . "\n"; // 0

// 9. С помощью array_filter и str_split
$str_split = "a1b2c3d4";
$chars = str_split($str_split);
$digits_arr = array_filter($chars, function($ch) {
    return ctype_digit($ch);
});
$result_filter = implode('', $digits_arr);
echo "Filter: $result_filter\n";

// 10. Регулярное выражение с захватом только групп цифр (альтернатива)
$text_groups = "ID: 12345, Pass: 67890";
preg_match_all('/\d+/', $text_groups, $groups);
$all_numbers = implode('', $groups[0]);
echo "Groups: $all_numbers\n";
?>
  
Unicode: 421000
Mixed: 123456
Empty result: '' (длина 0)
From signed: 15
Loop result: 7
From matches: 0071234
Phone: 18005550102
intval: 2019
intval2: 0
Filter: 1234
Groups: 1234567890
  
- подстрока строки php (поиск подстроки в строке php)
- Php только цифры (оставить только цифры в php)
- Php preg match (функция preg_match в php)
- Php убрать из строки (удаление подстроки в php)
- Php строки в файле (строки в файле php)

Оставить только цифры в PHP - comments

En
Php только цифры (php)