[Перевод] Escape-последовательности и числовые нотации в PHP

15 ИЮНЯ 2022

------------------------------------------------------------------------

Наш телеграм-канал: t.me/@mailsgun_online

Youtube: youtube.com/@mailsgun_online

------------------------------------------------------------------------

Автор оригинала: php.watch
  • Перевод

Привет, Хабр. В преддверии старта онлайн-курса «PHP-разработчик» подготовили традиционный перевод материала. Предлагаем также посмотреть запись прошедшего демо-занятия «Экосистема PHP».

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

Большинство символов можно просто набрать с клавиатуры и использовать в коде PHP в их исходном виде. Например, $string = "php.watch" — это полностью допустимая строка в PHP, а $num = 42 — допустимое число. Также можно использовать многобайтные символы (для хранения которых требуется более одного байта), например, этот совершенно допустимый эмодзи: $emoji = "?".

PHP, наряду со многими другими языками программирования, поддерживает определенное количество escape-последовательностей для использования различных символов, которые не могут быть набраны с обычной клавиатуры, не могут быть представлены в текстовой форме (например, невидимые символы или различные управляющие символы) или иным образом не считываются. Эти символы используют escape-последовательности, которые распознает PHP.

Что касается чисел, PHP поддерживает стандартные десятичные числа, но также может использовать и другие нотиции, такие как двоичное, восьмеричное, шестнадцатеричное и даже научное (scientific) представление. Они могут сделать код более читаемым и понятным в зависимости от контекста.

Двойные кавычки и Heredoc

В PHP строка с двойными кавычками ("string") или Heredoc (смотрите ниже) поддерживает escape-последовательности и интерполяцию переменных.

PHP будет пытаться интерполировать переменные, если строковый литерал находится внутри строки с двойными кавычками или Heredoc.

$name = 'John';
echo "Hi $name"; // "Hi John"
$name = 'John';
echo <<<HEREDOC
Hi $name
HEREDOC;
// "Hi John"

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

$name = 'John';
echo "Hi {$name}"; // "Hi John"

Строки в одинарных кавычках ('string') и синтаксис Nowdoc не интерполируют переменные:

$name = 'John';
echo 'Hi $name'; // "Hi $name"
$name = 'John';
echo <<<'NOWDOC'
Hi $name
NOWDOC;
// "Hi $name"

Только строки в двойных кавычках и Heredoc поддерживают escape-символы.

Экранирование символов

Поскольку PHP интерпретирует и интерполирует специальные символы внутри строковых литералов в двойных кавычках и heredoc, знак обратной косой черты () используется как «escape-символ».

Например, использование $name вместо $name не даст PHP интерполировать переменную $name.

$name = 'John';
echo "Hi $name"; // "Hi $name"

Использование второго символа обратной косой черты предотвращает преобразование первого символа обратной косой черты в escape-символ.

$name = 'John';
echo "Hi $name"; // "Hi John"

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

Символы табуляции: t и v

Возможно, самые простой из управляющих символов — это символ табуляции. Символ табуляции (по нажатию клавиши tab) можно использовать внутри строкового литерала, но использование t вместо визуального пропуска делает его наглядным. Использование t вместо буквального символа табуляции также позволяет избежать автоматической замены символов табуляции на пробелы в различных IDE.

echo "FootBar";
Foo Bar

v — это вертикальная табуляция. На поддерживаемых терминалах символ вертикальной табуляции переходит к следующему символу в следующей строке:

echo "FoovBarvBaz";
Foo
   Bar
      Baz

Новые строки: r и n

r («возврат каретки») и n («перевод строки») являются символами новой строки.

Исторически так сложилось, что различные системы начали использовать либо r, либо n, и даже Windows использует rn. Например, Linux и MacOS по умолчанию используют символ «перевода строки» (n) в качестве символа новой строки, тогда как Windows использует комбинацию rn (возврат каретки, за которым следует перевод строки). Старые системы MacOS использовали в качестве символа новой строки r.

PHP имеет константу PHP_EOL, которая всегда ссылается на системный символ новой строки.

echo "LeftnLeftnRightnRight";
Left
Left
Right
Right

Escape-символ: e

Escape-символы часто используется для отправки управляющих последовательностей ANSI в терминал. Например, e, за которым следует [32m, указывает терминалу изменить цвет на зеленый, а [33m — на желтый.

echo "e[32mGreen texte[0m e[33mYellow texte[0";

Если приведенный выше фрагмент выполняется в терминале, который поддерживает управляющие последовательности ANSI, он интерпретирует его и изменяет текст:

Символ новой страницы: f

Символ новой страницы — это управляющий символ ASCII для обозначения конца страницы. С его помощью принтеры могут вывести текущую страницу и начать с верхней части следующей. Когда f передается на дисплейный терминал, он может результировать в очистке экрана, хотя это очень редкое поведение для большинства программ эмуляции терминала.

Восьмеричные escape-последовательности символов ASCII 

PHP поддерживает экранирование восьмеричного числа в его соответствующий ASCII символ.

Например, ASCII символ P равен 80 в десятичной системе (смотрите диаграмму). 80 из десятичной системы счисления в переводе в восьмеричную — 120.

Для символа P можно использовать восьмеричную escape-последовательность:

echo "0";
P

Любой базовый символ ASCII можно представить с помощью такой записи:

echo "00071430";
PHP.Watch

Любое значение в диапазоне от {$content} до 7 будет интерпретироваться как восьмеричная escape-последовательность ASCII символа.

Обратите внимание, что числа для расширенных символов ASCII (от 128 до 255) несовместимы с UTF-8. PHP считает значение 128 (восьмеричное: 200; шестнадцатеричное: 80) недопустимым, поскольку оно не является допустимым значением UTF-8.

Хотя PHP принимает такие значения, они считаются недопустимыми символами в контексте UTF-8.

Шестнадцатеричные escape-последовательности символов ASCII

Подобно восьмеричным escape-последовательностям символов, PHP также допускает использование шестнадцатеричных чисел в escape-последовательности символов с префиксом x .

Допускается только один байт, что подразумевает допустимый диапазон от x0 до xFF. Однако ограничение UTF-8 по-прежнему присутствует, и только значения до x80 будут считаться допустимыми символами.

Кроме того, шестнадцатеричные символы не чувствительны к регистру (т.е. AF равно af и aF).

ASCII P — 80, что равно x50:

echo "x50";
P

Тот же «PHP.Watch» пример можно переписать с помощью шестнадцатеричных escape-последовательностей:

echo "x50x48x50x2Ex57x61x74x63x68";
PHP.Watch

Escape-последовательности символов Unicode

PHP поддерживает использование любого Unicode символа с префиксом u и шестнадцатеричным значением code point внутри фигурных скобок.

echo "u{1F418} - u{50}u{48}u{50}u{2E}u{57}u{61}u{74}u{63}u{68}";
? - PHP.Watch

PHP выдаст ошибку парсера, если символ Unicode превышает значение 10FFFF:

echo "u{10FFFF1}"
Invalid UTF-8 codepoint escape sequence: Codepoint too large on line ...

 10FFFF является верхним пределом, потому что спецификация UTF-8 объявляет диапазон от U+0000 до U+10FFFF.

В предыдущей версии этой статьи верхний предел неверно упоминался как FFFFF, что было исправлено на 10FFFF. Спасибо Саре Големон за то, что она указала на это.

Форму записи Unicode u{} можно использовать качестве escape-последовательности для любого символа. Вот несколько примеров:

Символ

Code point (Dec)

Code point (Hex)

Escape-последовательность Unicode

A

65

41

«u{41}»

B

66

42

«u{42}»

$

36

24

«u{24}»

€

8364

20AC

«u{20AC}»

n (перевод строки)

10

A

«u{A}»

r (возврат каретки)

13

D

«u{D}»

t (горизонтальная табуляция)

9

9

«u{9}»

v (вертикальная табуляция)

11

B

«u{B}»

e (управляющий символ)

27

1B

«u{1B}»

f (новая страница)

12

C

«u{C}»

?

128024

1F418

«u{1F418}»

අ

3461

D85

«u{D85}»

Двоичные строки

Несколько лет назад PHP 5.2.1 представил новый строковый синтаксис, названный «двоичными строками» (binary strings). Это с натяжкой можно было назвать синтаксисом, и он был задуман в рамках улучшение прямой совместимости с грядущим PHP 6.

Синтаксис заключался в добавлении префикса b к строкам в одинарных/двойных кавычках, чтобы PHP мог распознать это как двоичную строку.

echo b'Foo';
Foo

Функции is_binary, is_unicode и is_buffer должны были различать двоичные строки и строки Unicode в PHP 6, но они так и не добрались до следующей версии PHP 7. Однако синтаксис двоичной строки все-таки попал в PHP 7 и поддерживается в PHP 8.

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

Этот синтаксис не является устаревшим и не планируется к удалению в будущей версии PHP.

Числовые нотации

При использовании числовых литералов в PHP-скриптах PHP по умолчанию ожидает десятичные значения. Однако PHP также допускает другие числовые нотации, такие как двоичные числа, восьмеричные числа, шестнадцатеричные числа и научная нотация.

Начиная с PHP 7.4, PHP также позволяет разделять разряды нижнем подчеркиванием для лучшей читаемости длинных чисел.

Двоичная нотация

Любой числовой литерал, начинающийся с префикса 0b, будет считаться двоичным числом.

$number_binary  = 0b101010;

Для лучшей читаемости можно использовать разделитель разрядов в виде нижнего подчеркивания.

$number_binary = 0b10_1010;
0b101010  === 42; // true
0b10_1010 === 42; // true

Восьмеричная нотация

PHP принимает восьмеричные числовые значения с префиксом 0. Начиная с PHP 8.1, PHP также поддерживает явную восьмеричную числовую нотацию с префиксами 0O и 0o.

$number_octal = 052; // === Десятичное 42
$number_octal = 0o52; // === Десятичное 42
$number_octal = 0O52; // === Десятичное 42

Шестнадцатеричная нотация

Числа интерпретируются в шестнадцатеричные с помощью префиксов {$content}X и {$content}x.

$number_hex = 0x2A; // === Десятичное 42
$number_hex = 0X2A; // === Десятичное 42

Научная нотация (Scientific Notation)

PHP также поддерживает научную «E-нотацию» для значений с плавающей запятой.

$number_float = 42E1;

E-нотация эквивалентна 42 * 10^0 (10 в степени 0). Обратите внимание, что во многих языках программирования (включая PHP) оператор ^ используется для XOR, а для возведения в степень используется ** .

Преимущество удобочитаемости научной нотации более выражено для очень точных или больших чисел.

$planck_constant    = 6.62607004E-34;
$avogadros_constant = 6.022140857E+23;
3.844E5 === 3.844 * 10**5 === 384400.0; // true

PHP поддерживает различные формы escape-последовательностей и числовых обозначений. Недавно он добавил явную восьмеричную числовую нотацию с префиксами 0O/0o(PHP 8.1)и числовые разделители разрядов (PHP 7.4).

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

var_dump((int) "2_34_5");
// int(2)
var_dump((int) "0xabcd");
// int(0)

Escape-последовательности в пользовательском вводе, также не учитываются. Например, если форма содержит "", это значение будет использоваться как есть, без интерпретации как восьмеричная escape-последовательность для символа. А $str = "" выдаст "#", потому что в исходных файлах PHP это работает.

Узнать подробнее о курсе«PHP-разработчик»Смотреть запись прошедшего демо-занятия «Экосистема PHP».

Source: habr1

Ну и напоследок напоминаю вам о нашем новом проекте vkserfing bot.