Ctype punct: примеры (PHP)

Проверка символов пунктуации с помощью функции ctype_punct
Раздел: Работа со строками
ctype_punct(mixed $text): bool

Функция ctype_punct в PHP

Функция ctype_punct входит в семейство функций расширения Ctype, предназначенных для проверки типов символов. Она проверяет, состоит ли переданная строка только из знаков пунктуации.

Назначение и использование

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

Аргументы функции

Функция принимает один обязательный аргумент:
text (mixed) - Проверяемая строка. Начиная с PHP 8.1.0, передача нестрокового аргумента является устаревшей. Ранее, если передавалось целое число (int), оно трактовалось как ASCII-код символа.

Возвращаемое значение: bool - true, если каждый символ в строке text является печатным знаком пунктуации, и false в противном случае. Пустая строка вернет false.

К знакам пунктуации, которые проверяет функция, относятся символы, не являющиеся управляющими, буквами, цифрами или пробелами. Например: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

Примеры использования ctype_punct

Базовые примеры проверки строк

Проверка строки, состоящей только из знаков пунктуации:

$str1 = "!@#$";
var_dump(ctype_punct($str1));
bool(true)

Проверка строки, содержащей буквы:

$str2 = "Hello!";
var_dump(ctype_punct($str2));
bool(false)

Проверка строки, содержащей цифры:

$str3 = "123?.";
var_dump(ctype_punct($str3));
bool(false)

Проверка пустой строки:

$str4 = "";
var_dump(ctype_punct($str4));
bool(false)

Проверка строки с пробелом:

$str5 = "! ";
var_dump(ctype_punct($str5));
bool(false)

Похожие функции в PHP

Для проверки типов символов в строке можно использовать другие функции семейства Ctype, а также регулярные выражения.

Другие функции Ctype
  • ctype_alnum() - проверяет буквенно-цифровые символы.
  • ctype_alpha() - проверяет буквенные символы.
  • ctype_digit() - проверяет цифровые символы.
  • ctype_graph() - проверяет все печатные символы, кроме пробела. Эта функция близка к ctype_punct, но включает также буквы и цифры.
  • ctype_print() - проверяет печатные символы, включая пробел.
Регулярные выражения

Функция preg_match() предоставляет более гибкую проверку с помощью шаблонов PCRE.

$str = "!@#$";
$result = (preg_match('/^[\p{P}\p{S}]+$/u', $str) === 1);
var_dump($result);
bool(true)

Использование регулярных выражений предпочтительнее при работе с многобайтовыми кодировками (UTF-8) или когда требуется сложная логика проверки. Функции Ctype работают только с однобайтовыми символами (ASCII) и обычно быстрее.

Типичные ошибки использования

Передача нестрокового аргумента

До PHP 8.1 функция могла принимать целые числа, трактуя их как ASCII-коды. Теперь это вызывает предупреждение.

// До PHP 8.1
var_dump(ctype_punct(33)); // ASCII 33 = '!'

// Начиная с PHP 8.1
var_dump(ctype_punct(33));
// PHP < 8.1: bool(true)
// PHP >= 8.1: Deprecated: ctype_punct(): Argument of type int will be interpreted as string in the future
Непонимание области проверяемых символов

Функция проверяет только ASCII-знаки пунктуации. Символы пунктуации из других кодировок (например, кавычки-ёлочки «») не распознаются.

$str = "«Привет»";
var_dump(ctype_punct($str));
bool(false)
Ожидание true для пустой строки

Пустая строка возвращает false, что может быть неочевидно.

var_dump(ctype_punct(""));
bool(false)

Изменения в последних версиях PHP

В PHP 8.1.0 была изменена обработка нестроковых аргументов. Передача аргумента типа, отличного от string (int, float, null, bool, array, object и т.д.), теперь вызывает уведомление об устаревании (E_DEPRECATED). Функция продолжает работать, интерпретируя целые числа как ASCII-коды, но в будущих версиях ожидается, что она будет принимать только строки (string).

В версиях PHP до 8.1 нестроковые аргументы преобразовывались в целые числа и трактовались как код ASCII. Например, ctype_punct(46) проверяло, является ли символ с кодом 46 (точка '.') знаком пунктуации, и возвращало true.

В PHP 8 и более ранних версиях существенных изменений в поведении функции не было.

Расширенные примеры использования

Валидация пароля на наличие специальных символов

Функция может помочь в проверке, содержит ли пароль хотя бы один специальный символ, но не состоит исключительно из них.

Пример php
function validatePassword($pass) {
    if (strlen($pass) < 8) {
        return "Пароль слишком короткий";
    }
    if (ctype_alnum($pass)) {
        return "Пароль должен содержать хотя бы один специальный символ";
    }
    if (ctype_punct($pass)) {
        return "Пароль не может состоять только из специальных символов";
    }
    return "Пароль валиден";
}

echo validatePassword("Secure123") . "\n";
echo validatePassword("!@#$") . "\n";
echo validatePassword("Secur3!") . "\n";
Пароль должен содержать хотя бы один специальный символ
Пароль не может состоять только из специальных символов
Пароль валиден
Фильтрация строк для поиска «чистых» знаков пунктуации

Пример поиска подстрок, которые полностью состоят из пунктуации, в более длинном тексте.

Пример php
$text = "Привет! Как дела? Отлично... А у тебя? ;)";
$words = preg_split('/\s+/', $text);
$punctWords = [];

foreach ($words as $word) {
    // Удаляем возможные прилегающие буквенно-цифровые символы для проверки
    $cleanWord = preg_replace('/[\w\\s]/u', '', $word);
    if ($cleanWord !== '' && ctype_punct($cleanWord)) {
        $punctWords[] = $word;
    }
}

print_r($punctWords);
Array
(
    [0] => !
    [1] => ?
    [2] => ...
    [3] => ?
    [4] => ;)
)
Проверка символов в строке с предварительной обработкой

Поскольку функция работает только с ASCII, строку в UTF-8 можно предварительно обработать.

Пример php
function containsOnlyAsciiPunct($str) {
    // Преобразуем строку в ASCII, заменяя не-ASCII символы
    $asciiStr = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str);
    // Проверяем результат
    return ctype_punct($asciiStr);
}

$test1 = "!@#$";
$test2 = "¡Hola!"; // Испанский восклицательный знак

var_dump(containsOnlyAsciiPunct($test1));
var_dump(containsOnlyAsciiPunct($test2));
bool(true)
bool(false)
Генерация случайной строки из знаков пунктуации

Создание капчи или тестовых данных.

Пример php
function generatePunctString($length) {
    $punctChars = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
    $result = '';
    $max = strlen($punctChars) - 1;
    for ($i = 0; $i < $length; $i++) {
        $result .= $punctChars[random_int(0, $max)];
    }
    return $result;
}

$randomPunct = generatePunctString(5);
echo "Сгенерировано: " . $randomPunct . "\n";
echo "Проверка ctype_punct: " . (ctype_punct($randomPunct) ? 'true' : 'false');
Сгенерировано: ;{*^@
Проверка ctype_punct: true

Аналоги функции в других языках

Python

В Python для похожих проверок используют модуль string или методы строк.

import string

s = "!@#$"
result = all(c in string.punctuation for c in s)
print(result)  # True

# С пустой строкой
print(all(c in string.punctuation for c in ""))  # True (особенность all)
True
True
JavaScript

В JavaScript нет прямой встроенной функции. Обычно применяют регулярные выражения.

let str = "!@#$";
let regex = /^[!-\/:-@\[-\`\{-~]+$/;
console.log(regex.test(str));  // true
console.log(regex.test("a!")); // false
true
false
MySQL

В MySQL прямого аналога нет. Можно использовать оператор REGEXP.

SELECT '!@#$' REGEXP '^[[:punct:]]+$' AS is_punct;
is_punct: 1

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

PHP ctype_punct function comments

En
Ctype punct Check for any printable character which is not whitespace or an alphanumeric character