0Pricing
Lua Academy · Урок

Поиск и извлечение подстрок

Применяйте string.find и string.sub для поиска и извлечения текста.

«Поиск и извлечение подстрок» — бесплатный урок Lua Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Основы string.find

string.find(s, pattern, init, plain) ищет шаблон в s, начиная с позиции init (по умолчанию — 1). Функция возвращает начальную и конечную позиции совпадения или nil, если совпадение не найдено. При plain=true шаблон воспринимается как обычная строка, без специальных символов.

local s = "hello world"
local i, j = string.find(s, "world")
print(i, j)    -- 7  11

-- Plain search (literal string)
local i2, j2 = string.find("a+b=5", "+", 1, true)
print(i2, j2)  -- 2  2

-- Not found
print(string.find(s, "xyz"))  -- nil

Извлечение с помощью string.sub

string.sub(s, i, j) извлекает подстроку от позиции i до позиции j включительно. Отрицательные индексы отсчитываются с конца: -1 — это последний символ. Если j не указан, по умолчанию используется конец строки.

local s = "hello world"
print(string.sub(s, 1, 5))    -- hello
print(string.sub(s, 7))       -- world
print(string.sub(s, -5))      -- world
print(string.sub(s, 1, -7))   -- hello
print(s:sub(7, 11))           -- world (method syntax)

Объединение find и sub

Объединяйте string.find и string.sub, чтобы находить и извлекать подстроки. Сначала найдите разделитель, затем извлеките части по обе стороны от него. Это основной подход к разделению строк.

local s = "key=value"
local i = string.find(s, "=")
if i then
  local key = string.sub(s, 1, i - 1)
  local val = string.sub(s, i + 1)
  print(key, val)   -- key  value
end

string.match для захвата по шаблону

string.match(s, pattern, init) возвращает захваченные подстроки, соответствующие шаблону. Если шаблон не содержит захватов, функция возвращает всё совпадение. Если ничего не совпало, возвращается nil. Захваты задаются круглыми скобками в шаблоне.

local date = "2024-03-15"
local y, m, d = string.match(date, "(%d+)-(%d+)-(%d+)")
print(y, m, d)   -- 2024  03  15

-- No capture: returns the whole match
local num = string.match("price: 42.5 USD", "%d+%.%d+")
print(num)       -- 42.5

Поиск последнего вхождения

Чтобы найти последнее вхождение подстроки, выполняйте поиск в цикле, каждый раз продвигая начальную позицию, или ищите с конца. Стандартный подход: вызывайте string.find, передавая позицию сразу после предыдущего совпадения, пока функция не вернёт nil.

local function findLast(s, sub)
  local last_i, last_j
  local i, j = string.find(s, sub, 1, true)
  while i do
    last_i, last_j = i, j
    i, j = string.find(s, sub, j + 1, true)
  end
  return last_i, last_j
end

local i, j = findLast("a/b/c/d", "/")
print(i, j)   -- 6  6

Извлечение расширений файлов

Практический пример использования string.match: извлечение расширения из имени файла. Шаблон "([^%.]+)$" захватывает последнюю последовательность символов без точек в конце строки, а "%.([^%.]+)$" — только последовательность после последней точки.

local function getExt(filename)
  return string.match(filename, "%.([^%.]+)$")
end

print(getExt("photo.jpg"))        -- jpg
print(getExt("archive.tar.gz"))   -- gz
print(getExt("README"))           -- nil
print(getExt("config.lua.bak"))   -- bak

Разделение строк

В Lua нет встроенной функции разделения строк, но её можно реализовать с помощью string.gmatch. Перебирайте все последовательности символов, не являющиеся разделителями, или используйте шаблон, который захватывает содержимое между разделителями.

local function split(s, sep)
  local result = {}
  local pattern = "([^" .. sep .. "]+)"
  for part in string.gmatch(s, pattern) do
    result[#result+1] = part
  end
  return result
end

local parts = split("one,two,three,four", ",")
for i, p in ipairs(parts) do
  print(i, p)
end
-- 1 one  2 two  3 three  4 four

Удаление пробельных символов

Удаляйте пробельные символы в начале и конце строки, сопоставляя их и отбрасывая. Шаблон "^%s*(.-)%s*$" использует ленивый квантификатор .-, чтобы захватить минимальное содержимое между необязательными пробелами в начале и конце.

local function trim(s)
  return string.match(s, "^%s*(.-)%s*$")
end

print("|" .. trim("  hello  ") .. "|")  -- |hello|
print("|" .. trim("  \t\n") .. "|")    -- ||
print("|" .. trim("no spaces") .. "|")  -- |no spaces|

Извлечение чисел из текста

Используйте string.gmatch с шаблоном числа, чтобы извлечь из строки все числа. Шаблон %-?%d+%.?%d* соответствует необязательному знаку минус, цифрам, необязательной десятичной точке и последующим цифрам.

local text = "Revenue: $1,234.56 Expenses: $567.89 Net: $666.67"
local numbers = {}
for n in string.gmatch(text, "%d+%.?%d*") do
  numbers[#numbers+1] = tonumber(n)
end
for _, v in ipairs(numbers) do
  io.write(v .. " ")
end
print()  -- 1 234.0 56.0 567.89 666.67

Нормализация позиций в строке

Отрицательные индексы Lua позволяют работать с конца строки. string.sub(s, -n) получает последние n символов. Для вычисления позиций используйте эту возможность вместе с #s. Понимание связи между положительными и отрицательными индексами помогает избежать ошибок на единицу.

local s = "abcdefgh"

-- Last 3 characters
print(s:sub(-3))     -- fgh

-- All but last 2
print(s:sub(1, -3))  -- abcdef

-- Character at position from end
print(s:sub(-1, -1)) -- h
print(s:sub(-4, -2)) -- efg

Быстрая проверка

Что возвращает string.sub("hello", 2, -2)?

Итоги: поиск и извлечение

Краткое повторение:

  • string.find(s, pat, init, plain) — возвращает начальную и конечную позиции или nil
  • string.sub(s, i, j) — извлекает по позициям; отрицательные индексы отсчитываются с конца
  • string.match(s, pat) — возвращает захваты или всё совпадение
  • Используйте plain=true для буквального поиска, без специальных символов
  • Реализуйте разделение строк с помощью string.gmatch
  • Для удаления пробелов используйте шаблон "^%s*(.-)%s*$"

Часто задаваемые вопросы

Урок «Поиск и извлечение подстрок» бесплатный?

Да — полный текст урока «Поиск и извлечение подстрок» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «Поиск и извлечение подстрок»?

Применяйте string.find и string.sub для поиска и извлечения текста. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Поиск и извлечение подстрок»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы строк: объединение и длина
  2. Поиск и извлечение подстрок
  3. string.format для вывода
  4. string.gsub и string.gmatch
← Назад к Lua Academy