Для разбора строки по шаблону есть четыре функции: string.find,
string.gsub, string.match и string.gmatch. Все они требуют, собственно,
шаблон.
Шаблон — это строка, абстрактно описывающая содержимое других строк. Например,
шаблон "%d" описывает любую строку, состояющую из одной цифры (то есть
"0", "1", "2", "3", "4", "5", "6", "7", "8" и "9").
Шаблон является последовательностью элементов шаблона и захватов.
Самые простые элементы шаблона — это классы символов.
| Класс символов | Описание |
|---|---|
x |
Если символ x не является одним из `^$()%.[]*+-?`, то представляет самого себя |
. |
Любой символ |
%a |
Все буквы латинского алфавита |
%c |
Все управляющие символы (\x00 — \x1f и \x7f) |
%d |
Все цифры |
%g |
Все символы, которые можно вывести на экран, кроме пробела (т.е. у них есть глифы) |
%l |
Все символы в нижнем регистре |
%p |
Все символы пунктуации |
%s |
Все пробельные символы |
%u |
Все символы в верхнем регистре |
%w |
Все цифры и буквы |
%x |
Все шестнадцатеричные цифры |
%char |
Символ char |
[классы символов] |
Набор — представляет любой из составных классов. Можно использовать как обычные символы, так и %-классы. Чтобы включить в набор символ ], нужно указать его первым символом ([]+%wa-f]). Диапазон символов указывается нижней границей, символом - и верхней границей ([a-zA-Z]). Сам символ - можно добавить в набор указав последним или первым. Символ % нужно экранировать (%%). |
[^классы символов] |
Инвертированный набор — все символы, кроме соответствующих перечисленным классам. |
Если %-класс символов записать с большой буквой, то класс инвертируется.
Например, %S — все символы, кроме пробельных.
Класс символов может быть составной частью элемента шаблона. Все элементы:
*. Соответствует нулю или более символов из класса. Жадное
соответствие: пытается найти как можно больше символов, чтобы всё ещё
соответствовать шаблону.+. Соответствует одному и более символам из класса. Жадное
соответствие.-. Соответствует нулю или более символов из класса. В
отличие от *, находит минимальное кол-во символов, чтобы соответствовало
шаблону.?. Соответствует нулю или одному символу.%n. Соответствует содержимому энного захвата.%bxy. Для двух символов (не классов) x и y находит
соответствие так, чтобы x и y были сбалансированы. Для символа x
счётчик увеличивается на 1, для символа y — уменьшается на 1, в
соответствии счётчик равен нулю. Полезно, чтобы искать сбалансированные
скобки (%b()), например.%f[набор]. Соответствует пустой строке такой позиции,
что следующий символ соответствует набору, а предыдущий не соответствует.
Конец и начало строки принимаются за нулевой байт \0.Шаблон может начинаться с ^ — будет искаться соответствие с начала
строки — или $ — тогда с конца. Если оба символа указать, то шаблон
проверяться будет на всю строку.
Шаблон может содержать захваты — подшаблоны, значения которых возвращается.
Они обозначаются круглыми скобками и нумеруются в порядке появления левых
скобок. Например, в шаблоне ((..)((%d+)%s))%s первым будет (..)((%d+)%s),
вторым — (..), третьим — (%d+)%s, четвёртым — %d+.
Если захват пустой, то вернётся число — текущая позиция матчера в строке.
Шаблоны можно скармливать в четыре функции стандартной либы string:
string.find(str: string, pattern: string[, init: number[, plain: boolean]]) —
ищет в строке str первое совпадение шаблона pattern и возвращает индексы
начала и конца. Если совпадения не найдено, вернёт nil. Захваты в шаблоне,
если они есть, возвращаются после индексов.string.match(str: string, pattern: string[, init: number]) — также ищет в
строке str шаблон pattern. Возвращает захваты из первого совпадения или
всё совпадение, если захватов нет.string.gmatch(str: string, pattern: string) — то же, что и string.match,
но возвращает итератор, который отдаёт каждое совпадение шаблона pattern в
строке str. Итератор можно использовать в цикле for in.string.gsub(str: string, pattern: string, repl[, n: number]) —
заменяет в строке str совпадения шаблона pattern на значение, определяемое
аргументом repl: если это строка, то на эту строку будет заменяться; если
это таблица — на строку по ключу, соответствующую совпадению; если это
функция — на возвращаемое значение функции.print(string.find("string 123", "(%d+)"))
--> 8 10 123
-- Парсить даты
print(string.match("2048-01-02 04:08:16",
"(%d%d%d%d)-(%d%d)-(%d%d) (%d%d):(%d%d):(%d%d)"))
--> 2048 01 02 04 08 16
-- Делить строку по разделителю (например, запятой)
for match in string.gmatch("item1, item2, item3, item4",
"%s*([^,]+)") do
print(("%q"):format(match))
end
--> "item1"
--> "item2"
--> "item3"
--> "item4"
-- Убрать пробелы в начале и в конце строки
local s = " test test "
print(("%q"):format((string.gsub(s, "^%s*(.-)%s*$", "%1"))))
--> "test test"
-- Интерполяция по значениям из таблицы
print(string.gsub("${name}-${version}.tar.gz", "%${(.-)}", {
name = "lua",
version = "5.3"
}))
--> lua-5.3.tar.gz 2
num1 = 32
num2 = 128
-- Интерполяция результата выполнения произвольного кода
-- (локальные переменные не увидит)
print(string.gsub("${num1} * ${num2} = ${num1 * num2}", "%$(%b{})",
function(match)
-- `match` содержит знаки `{` и `}`, поэтому их обрезаем:
match = match:sub(2, -2)
-- Исполняем полученный код как выражение
local chunk = load("return " .. match, match, "t")
if not chunk then
return assert(load(match))()
else
return chunk()
end
end))
--> 32 * 128 = 4096 3