Finding Text

Does Grandpa Joe's note say anything about rain? Where in a text does a word start? The method find searches a text for another text. It gives two numbers: the position where the found text starts and the position where it ends. When the text isn't there, it gives nil:

local note = "Hugo wants 12 pumpkins"
print(note:find("pumpkins", 1, true))
print(note:find("carrots", 1, true))

This prints:

15	22
nil

What are the 1 and the true? The number says where to start searching: from the first character. true says that you're looking for exactly the text you wrote. Without it, find takes the text as a pattern, in which some characters have a special meaning. You'll learn patterns later in this lesson; for now, one example. In a pattern, a dot means “any character”, so find(".") finds the very first character, whatever it is:

local price = "Price: 3.50"
print(price:find(".", 1, true))
print(price:find("."))

This prints:

9	9
1	1

So when you look for an exact text, always add 1, true. With letters only, such as "pumpkins", find would work without them too, but with a period, a parenthesis or a percent sign, it wouldn't.

In a condition, nil counts as false and any number as true. So you can put find straight into an if, to check whether a text contains another one:

local weather = "Cloudy, rain in the evening"
if weather:find("rain", 1, true) then
    print("Bring the hens inside")
end

This prints:

Bring the hens inside

find tells capital and small letters apart: in "Rain all day", it doesn't find "rain". When the case doesn't matter, search the text in small letters: weather:lower():find("rain", 1, true).

The positions that find gives fit sub. This is how you cut a text in two at a colon:

local entry = "Bella: 18 liters"
local colon = entry:find(":", 1, true)
print(entry:sub(1, colon - 1))
print(entry:sub(colon + 2))

This prints:

Bella
18 liters

When you store the result of find in one variable, you get the first number, the start; the second one is dropped. For both, write two variables, local first, last = entry:find(":", 1, true), as with any function that returns two values.

Typical mistake: using the position without checking it. When the text has no colon, colon is nil, and colon - 1 ends the program:

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')

When you aren't sure the text is there, check the result with an if first.

Instructions

Does Hugo want pumpkins? And potatoes? Check both with find and an if, and print:

Pumpkins: yes
Potatoes: no

Emma wants to write just the order on the board, without the rest of the message. Find the first period with find, and print the message up to it, the period included:

I need 12 pumpkins and 30 carrots.

Then print the rest of the message, which starts two characters after the period (there's a space in between): I'll come on Friday.

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

3/9