LUA gsub Returns Unexpected Values

Viewed 57

I've been working on learning LUA, and I've run into a confusing issue. When I try to print the following value, it returns 5. Where is this 5 coming from?

print(tonumber(string.gsub("spawn10", "%D", ""))) -- 5

If I instead print it without casting it to an int, I get an even weirder response.

print(string.gsub("spawn10", "%D", "")) -- 10   5

Perhaps my understanding of gsub is incorrect, but I don't get where these 5s are coming from.

2 Answers

Your call is basically taking the string value 10 and converting it to a number in base 5 which results in the number 5. This happens because tonumber can take more than 1 parameter, the optional second paramater base

When called with base, then e must be a string to be interpreted as an integer numeral in that base. The base may be any integer between 2 and 36, inclusive.

Lua 5.4 Reference Manual - tonumber (e [, base])

So what you are doing is calling tonumber by passing ALL the results from gsub this include the second return value which indicates the number of matches that happened.

Returns a copy of s in which all (or the first n, if given) occurrences of the pattern (see §6.4.1) have been replaced by a replacement string specified by repl, which can be a string, a table, or a function. gsub also returns, as its second value, the total number of matches that occurred. The name gsub comes from Global SUBstitution.

Lua 5.4 Reference Manual - string.gsub (s, pattern, repl [, n])


There are a few ways to fix this, specify the base in your tonubmer call

print(tonumber(string.gsub("spawn10", "%D", ""),10))

or as you discovered wrapping the gsub call in (

print(tonumber((string.gsub("spawn10", "%D", ""))))

Both of these accomplish the same thing by discarding all but the first value returned by gsub.

This mechanism is described in Lua 5.4 Reference Manual: 3.4 – Expressions

If a function call is used as a statement (see §3.3.6), then its return list is adjusted to zero elements, thus discarding all returned values. If an expression is used as the last (or the only) element of a list of expressions, then no adjustment is made (unless the expression is enclosed in parentheses). In all other contexts, Lua adjusts the result list to one element, either discarding all values except the first one or adding a single nil if there are no values.

Marking as answered as per my findings here: Lua string.gsub without printing match count

Looks like gsub returns the number of matched characters when not surrounded in parentheses. Parentheses force the returned value of gsub into a single result.

"Just to make it clearer on why it works - the parentheses around string.gsub force the expression into a single value (the first value or nil). See manual for details." - Michal Kottman

Related