1

I want to convert this Python code to Lua (nmap script):

for i in range(1000, 9999):
    if str(i).endswith('9'):
        print(i)

I've come this far:

for var = 1000, 9000 then
    if tostring(var).endswith('9') then
        print (var)
    end
end

but I don't know the Lua equivalent of endswith().

Luatic
  • 8,513
  • 2
  • 13
  • 34
  • There isn't one, I think. You can write one. – user253751 Jul 09 '22 at 12:35
  • Does this answer your question? [How to match the start or end of a string with string.match in Lua?](https://stackoverflow.com/questions/10159817/how-to-match-the-start-or-end-of-a-string-with-string-match-in-lua) – Karl Knechtel Jul 09 '22 at 12:48
  • Karl Knechtel: Not really - `string.match` is only one approach that can be taken here. – Luatic Jul 09 '22 at 14:04

3 Answers3

4

XY-Problem

The X problem of how to best port your code to Lua has been answered by quantumpro already, who optimized it & cleaned it up.

I'll focus on your Y problem:

What's the Lua equivalent of Python endswith?

Calling string functions, OOP-style

In Lua, strings have a metatable that indexes the global string library table. String functions are called using str:func(...) in Lua rather than str.func(...) to pass the string str as first "self" argument (see "Difference between . and : in Lua").

Furthermore, if the argument to the call is a single string, you can omit the parentheses, turning str:func("...") into str:func"...".

Constant suffix: Pattern Matching

Lua provides a more powerful pattern matching function that can be used to check whether a string ends with a suffix: string.match. str.endswith("9") in Python is equivalent to str:match"9$" in Lua: $ anchors the pattern at the end of the string and 9 matches the literal character 9.

Be careful though: This approach doesn't work with arbitrary, possibly variable suffices since certain characters - such as $ - are magic characters in Lua patterns and thus have a special meaning. Consider str.endswith("."); this is not equivalent to string:match".$" in Lua, since . matches any character.

I'd say that this is the lua-esque way of checking whether a string ends with a constant suffix. Note that it does not return a boolean, but rather a match (the suffix, a truthy value) if successful or nil (a falsey value) if unsuccessful; it can thus safely be used in ifs. To convert the result into a boolean, you could use not not string:match"9$".

Variable suffix: Rolling your own

Lua's standard library is very minimalistic; as such, you often need to roll your own functions even for basic things. There are two possible implementations for endswith, one using pattern matching and another one using substrings; the latter approach is preferable because it's shorter, possibly faster (Lua uses a naive pattern matching engine) and doesn't have to take care of pattern escaping:

function string:endswith(suffix)
    return self:sub(-#suffix) == suffix
end

Explanation: self:sub(-#suffix) returns the last suffix length characters of self, the first argument. This is compared against the suffix.

You can then call this function using the colon (:) syntax:

str = "prefixsuffix"
assert(str:endswith"suffix")
assert(not str:endswith"prefix")
Luatic
  • 8,513
  • 2
  • 13
  • 34
2

The python code is not great, you can get the last digit by using modulo %

# python code using modulo
for i in range(1000,9999):
    if i % 10 == 9:
        print(i)

This also works in Lua. However Lua includes the last number in the loop, unlike python.

-- lua code to do this
for i=1000, 9998 do
    if i % 10 == 9 then
        print(i)
    end
end

However in both languages you could iterate by 10 each time

for i in range(1009, 9999, 10):
    print(i)
for i=9, 9998, 10 do
    print(i)
Shaw Summa
  • 21
  • 1
  • 2
0
for var = 1000, 9000 do
  if string.sub(var, -1) == "9" then
     -- do your stuff
  end
end