Поиск в строке
Есть ли в записке дедушки Джо что-нибудь про дождь? С какого места в строке начинается слово? Метод find ищет в строке другую строку. Он возвращает два числа: позицию, где найденный текст начинается, и позицию, где он заканчивается. Если такого текста нет, он возвращает nil:
local note = "Hugo wants 12 pumpkins"
print(note:find("pumpkins", 1, true))
print(note:find("carrots", 1, true))Он выводит:
15 22
nilЧто за 1 и true? Число говорит, с какого места искать: с первого символа. true говорит, что вы ищете ровно тот текст, который написали. Без него find воспринимает текст как шаблон, в котором некоторые символы имеют особый смысл. О шаблонах вы узнаете дальше в этом уроке, а пока один пример. В шаблоне точка означает «любой символ», поэтому find(".") находит самый первый символ, какой бы он ни был:
local price = "Price: 3.50"
print(price:find(".", 1, true))
print(price:find("."))Он выводит:
9 9
1 1Поэтому, когда ищете точный текст, всегда добавляйте 1, true. Для одних только букв, как в "pumpkins", find сработал бы и без них, а вот с точкой, скобкой или знаком процента — нет.
В условии nil считается ложью, а любое число — истиной. Поэтому find можно поставить прямо в if, чтобы проверить, содержит ли строка другую строку:
local weather = "Cloudy, rain in the evening"
if weather:find("rain", 1, true) then
print("Загоните кур в курятник")
endОн выводит:
Загоните кур в курятникfind различает заглавные и строчные буквы: в "Rain all day" он не найдёт "rain". Если регистр не важен, ищите в строке, переведённой в нижний регистр: weather:lower():find("rain", 1, true).
Позиции, которые возвращает find, подходят для sub. Так строку разрезают надвое по двоеточию:
local entry = "Bella: 18 liters"
local colon = entry:find(":", 1, true)
print(entry:sub(1, colon - 1))
print(entry:sub(colon + 2))Он выводит:
Bella
18 litersЕсли сохранить результат find в одну переменную, получится первое число, начало; второе отбрасывается. Чтобы получить оба, напишите две переменные: local first, last = entry:find(":", 1, true), как с любой функцией, которая возвращает два значения.
Типичная ошибка: использовать позицию, не проверив её. Если в строке нет двоеточия, colon равно nil, а colon - 1 завершает программу ошибкой:
local entry = "Bella 18 liters"
local colon = entry:find(":", 1, true)
print(entry:sub(1, colon - 1))main.lua:3: attempt to perform arithmetic on a nil value (local 'colon')Если вы не уверены, что нужный текст есть, сначала проверьте результат с помощью if.
Задание
- 1
Нужны ли Гуго тыквы (в сообщении pumpkins)? А картофель (potatoes)? Проверьте оба слова с помощью
findиifи выведите:Тыквы: да Картофель: нет - 2
Эмма хочет написать на доске только сам заказ, без остальной части сообщения. Найдите первую точку с помощью
findи выведите сообщение до неё, включая точку:I need 12 pumpkins and 30 carrots. - 3
Затем выведите остаток сообщения, который начинается через два символа после точки (между ними пробел):
I'll come on Friday.