4.7 Форматирование строк

Форматирование означает создание строки путём подстановки вычисленных значений в различные места постоянной строки. Эта постоянная строка управляет тем, как печатаются другие значения, а также где они появляются; она называется строкой формата.

Форматирование часто полезно для составления сообщений, которые должны отображаться. Фактически, функции message и error предоставляют ту же возможность форматирования, что описана здесь; они отличаются от format-message только тем, как используют результат форматирования.

Функция: format строка &rest объекты

Эта функция возвращает строку, равную строке, заменяя любые спецификации формата кодировками соответствующих объектов. Аргументы объекты — это вычисляемые значения для форматирования.

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

Выходная строка не обязательно должна быть заново выделена. Например, если x — это строка "foo", выражения (eq x (format x)) и (eq x (format "%s" x)) могут оба вернуть t.

Функция: format-message строка &rest объекты

Эта функция действует как format, но также преобразует любые грависы (`) и апострофы (') в строке в соответствии со значением text-quoting-style.

Обычно гравис и апостроф в формате преобразуются в соответствующие изогнутые кавычки, например, "Missing `%s'" может дать "Missing ‘foo’". См. Стиль текстовых кавычек, о том, как влиять на это преобразование или подавлять его.

Спецификация формата — это последовательность символов, начинающаяся с ‘%’. Таким образом, если в строке есть ‘%d’, функция format заменяет его печатным представлением одного из значений, подлежащих форматированию (одного из аргументов объекты). Например:

(format "Значение fill-column равно %d." fill-column)
     ⇒ "Значение fill-column равно 72."

Поскольку format интерпретирует символы ‘%’ как спецификации формата, вам никогда не следует передавать произвольную строку в качестве первого аргумента. Это особенно важно, когда строка генерируется каким-либо кодом Lisp. Если не известно, что строка никогда не содержит символов ‘%’, передайте "%s" (описано ниже) в качестве первого аргумента, а строку — вторым, например:

  (format "%s" произвольная-строка)

Некоторые спецификации формата требуют значений определённых типов. Если вы передадите значение, не соответствующее требованиям, будет вызвана ошибка.

Вот таблица допустимых спецификаций формата:

‘%s’

Заменяет спецификацию печатным представлением объекта, выполненным без кавычек (то есть с использованием princ, а не prin1 — см. Функции вывода). Таким образом, строки представляются только своим содержимым, без символов ‘"’, а символы (symbols) отображаются без символов ‘\’.

Если объект является строкой, его текстовые свойства копируются в вывод. Текстовые свойства самой ‘%s’ также копируются, но свойства объекта имеют приоритет.

‘%S’

Заменяет спецификацию печатным представлением объекта, выполненным с кавычками (то есть с использованием prin1 — см. Функции вывода). Таким образом, строки заключаются в символы ‘"’, а символы ‘\’ появляются там, где это необходимо перед специальными символами.

‘%o’

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

‘%d’

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

‘%x’
‘%X’

Заменяет спецификацию шестнадцатеричным представлением целого числа. Отрицательные целые числа форматируются платформо-зависимым способом. ‘%x’ использует строчные буквы, а ‘%X’ — прописные. Объект также может быть числом с плавающей запятой, которое форматируется как целое, с отбрасыванием дробной части.

‘%c’

Заменяет спецификацию символом, значение которого передано.

‘%e’

Заменяет спецификацию экспоненциальной записью числа с плавающей запятой.

‘%f’

Заменяет спецификацию записью с десятичной точкой для числа с плавающей запятой.

‘%g’

Заменяет спецификацию записью числа с плавающей запятой, используя либо экспоненциальную нотацию, либо запись с десятичной точкой. Экспоненциальная нотация используется, если показатель степени меньше −4 или больше или равен точности (по умолчанию: 6). По умолчанию конечные нули удаляются из дробной части результата, а символ десятичной точки появляется только в том случае, если за ним следует цифра.

‘%%’

Заменяет спецификацию одним символом ‘%’. Эта спецификация формата необычна тем, что её единственная форма — это просто ‘%%’, и она не использует значение. Например, (format "%% %d" 30) возвращает "% 30".

Любой другой символ формата приводит к ошибке ‘Invalid format operation’ (недопустимая операция форматирования).

Вот несколько примеров, предполагающих типичные настройки text-quoting-style:

(format "Восьмеричное значение %d равно %o,
         а шестнадцатеричное — %x." 18 18 18)
     ⇒ "Восьмеричное значение 18 равно 22,
         а шестнадцатеричное — 12."

(format-message
 "Имя этого буфера — ‘%s’." (buffer-name))
     ⇒ "Имя этого буфера — ‘strings.texi’."

(format-message
 "Объект буфера печатается как `%s'." (current-buffer))
     ⇒ "Объект буфера печатается как ‘strings.texi’."

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

Спецификация формата может иметь номер поля — десятичное число сразу после начального ‘%’, за которым следует буквальный знак доллара ‘$’. Это заставляет спецификацию формата преобразовывать аргумент с указанным номером вместо следующего аргумента. Номера полей начинаются с 1. Формат может содержать либо нумерованные, либо ненумерованные спецификации формата, но не оба одновременно, за исключением того, что ‘%%’ может смешиваться с нумерованными спецификациями.

(format "%2$s, %3$s, %%, %1$s" "x" "y" "z")
     ⇒ "y, z, %, x"

После ‘%’ и любого номера поля можно поместить определённые флаговые символы.

Флаг ‘+’ вставляет знак плюс перед неотрицательным числом, так что оно всегда имеет знак. Пробел в качестве флага вставляет пробел перед неотрицательным числом. (В противном случае неотрицательные числа начинаются с первой цифры.) Эти флаги полезны для обеспечения того, чтобы неотрицательные и отрицательные числа использовали одинаковое количество столбцов. Они игнорируются, за исключением ‘%d’, ‘%e’, ‘%f’, ‘%g’, и если используются оба флага, ‘+’ имеет приоритет.

Флаг ‘#’ задаёт альтернативную форму, которая зависит от используемого формата. Для ‘%o’ он гарантирует, что результат начинается с ‘0’. Для ‘%x’ и ‘%X’ он добавляет к ненулевым результатам префикс ‘0x’ или ‘0X’. Для ‘%e’ и ‘%f’ флаг ‘#’ означает включение десятичной точки, даже если точность равна нулю. Для ‘%g’ он всегда включает десятичную точку, а также заставляет оставлять все конечные нули после десятичной точки на своих местах, которые в противном случае были бы удалены.

Флаг ‘0’ гарантирует, что заполнение состоит из символов ‘0’ вместо пробелов. Этот флаг игнорируется для нечисловых символов спецификации, таких как ‘%s’, ‘%S’ и ‘%c’. Эти символы спецификации принимают флаг ‘0’, но всё равно заполняются пробелами.

Флаг ‘-’ приводит к тому, что любое заполнение, вставляемое по ширине (если она указана), вставляется справа, а не слева. Если присутствуют и ‘-’, и ‘0’, флаг ‘0’ игнорируется.

(format "%06d дополнено слева нулями" 123)
     ⇒ "000123 дополнено слева нулями"

(format "'%-6d' дополнено справа" 123)
     ⇒ "'123   ' дополнено справа"

(format "Слово '%-7s' содержит %d букв."
        "foo" (length "foo"))
     ⇒ "Слово 'foo    ' содержит 3 буквы."

Спецификация может иметь ширину — десятичное число, которое появляется после любого номера поля и флагов. Если печатное представление объекта содержит меньше символов, чем эта ширина, format дополняет его заполнением. Любое заполнение, вводимое шириной, обычно состоит из пробелов, вставляемых слева:

(format "%5d дополнено слева пробелами" 123)
     ⇒ "  123 дополнено слева пробелами"

Если ширина слишком мала, format не усекает печатное представление объекта. Таким образом, вы можете использовать ширину для задания минимального расстояния между столбцами без риска потери информации. В следующих двух примерах ‘%7s’ задаёт минимальную ширину 7. В первом случае строка, вставляемая вместо ‘%7s’, содержит всего 3 буквы и требует 4 пробела в качестве заполнения. Во втором случае строка "specification" имеет ширину 13 букв, но не усекается.

(format "Слово '%7s' содержит %d букв."
        "foo" (length "foo"))
     ⇒ "Слово '    foo' содержит 3 буквы."
(format "Слово '%7s' содержит %d букв."
        "specification" (length "specification"))
     ⇒ "Слово 'specification' содержит 13 букв."

Все символы спецификации допускают необязательную точность после номера поля, флагов и ширины (если они присутствуют). Точность — это десятичная точка ‘.’, за которой следует строка цифр. Для спецификаций с плавающей запятой (‘%e’ и ‘%f’) точность указывает, сколько цифр после десятичной точки показывать; если точность равна нулю, сама десятичная точка также опускается. Для ‘%g’ точность указывает, сколько значащих цифр показывать (значащие цифры — это первая цифра перед десятичной точкой и все цифры после неё). Если точность %g равна нулю или не указана, она рассматривается как 1. Для ‘%s’ и ‘%S’ точность усекает строку до заданной ширины, так что ‘%.3s’ показывает только первые три символа представления объекта. Для других символов спецификации эффект точности определяется тем, что производят локальные библиотечные функции семейства printf.

Если вы планируете впоследствии использовать read для отформатированной строки, чтобы получить копию отформатированного значения, используйте спецификацию, которая позволяет read восстановить значение. Для обратимого форматирования чисел можно использовать ‘%s’ и ‘%S’; для форматирования только целых чисел можно также использовать ‘%d’, а для форматирования только неотрицательных целых чисел — ‘#x%x’ и ‘#o%o’. Другие форматы могут быть проблематичными; например, ‘%d’ и ‘%g’ могут некорректно обрабатывать значения NaN, терять точность и тип, а ‘#x%x’ и ‘#o%o’ могут некорректно обрабатывать отрицательные целые числа. См. Функции ввода.

Функции, описанные в этом разделе, принимают фиксированный набор символов спецификации. В следующем разделе описывается функция format-spec, которая может принимать пользовательские символы спецификации, такие как ‘%a’ или ‘%z’.