# Is there a way to find the position of a matched string?

Suppose I have a string (PlayerCodeString) that a player defines, but I know what the string is in this case: “Hey, the code is 123. I repeat: the code is 123.”

The code can be anything as the player defines, but I know it’s a number, so I know I can use string.match(PlayerCodeString, "%d+") to get the code. I can also use string.gmatch(PlayerCodeString, "%d+") to verify that the code the player defines is the same.

But I want to get the position of the matches. I know I can use string.find(PlayerCodeString, "%d+") to find the position of the first occurrence, but I don’t think I can find the second one by simply using this function.

Is there a way to find the positions of the matches?

1 Like

string.find has an argument where you can tell it the nth occurrence of the pattern

you could use something like this

local occurrence = 2
local s, e = string.find(PlayerCodeString, "%d+", occurrence)

2 Likes

I think the third argument in string.find() is the position of the string of where to start looking for a substring.

> print(string.find("Hey, the code is 123. I repeat: the code is 123.", "%d+",2))

18 20

> print(string.find("Hey, the code is 123. I repeat: the code is 123.", "%d+"));

18 20

This returns the same position.

bruh i am a idiot

u could do something like this then

local str = ""
local pat = ""
local len_offset = 0
local occurs = {}
repeat
local s, e = string.find(str, pat)
if e then
table.insert(occurs, #occurs + 1, {s+len_offset, e+len_offset})
str = string.sub(str, e+1)
len_offset = len_offset + e
end
until (not s)


I would imagine there is a better way but I am not really friends with strings

5 Likes

Works for me; just wanted to know if it was possible.

Thank you!

1 Like

I know this has been solved, but…

if you want to get the position of a certain character in a string then there’s more than one method, way more than 1.

1. Using string.find()

this is probably the canonical way to do get the position of an element :

str = "I repeat the code is 123"

local position = string.find(str,"r")
print(position) --> 3 , as whitespaces count as characters


A function for it,

  function getPosition(str,char)

local find = string.find(str,char)
return find
end


My own invented function, made this a long time ago (ignore parameter init) (also uncertain about it's efficiency)
   function nmatch(s,pattern,init)
if type(s) == "string"    then
else
return nil
end
if init  then
local sub = s:sub(init)
if  sub:match(pattern)
then for i = 1,#sub do
if sub:sub(i,i) == pattern then
else
i = nil
return i

end
end

return
end
end

if not init then
if s:match(pattern) then
for i = 1,#s do
if s:sub(i,i) == pattern then
return i
end
end
else
return nil
end
end
end


print(nmatch("strring","r")) ---> first occurence is at 3, so 3 prints

2 Likes

There’s even a way to do it with gmatch, using the empty capture pattern. This pattern, (), captures the position it’s before. For example,

for start, word, end_plus_one in string.gmatch("hello world", "()(%w+)()") do
print(word, start, end_plus_one - 1)
end


prints hello 1 5 and world 7 11.

5 Likes

Woah! That’s the simplest one I’ve seen! I wish I could mark multiple solutions.

1 Like

Although the solution is correct. I tried to use it on my “HighlightTheSameText” Script and then it almost crashed my game when I highlighted the text that will detect if there is more and then find it’s position.

At least the script timed out for throwing 50,000 events very fast.

# Script.

wait(1)
local textBox = script.Parent.Parent

local function showSelection()
local Found = 0
if textBox.CursorPosition == -1 or textBox.SelectionStart == -1 then return end

local selectedText = string.lower(string.sub(
textBox.Text,
math.min(textBox.CursorPosition, textBox.SelectionStart),
math.max(textBox.CursorPosition, textBox.SelectionStart)
))
local TextboxText = string.lower(textBox.Text)
if selectedText == "" then return end

local matches = {}
local matchesPosition = {}
for m in string.gmatch(textBox.Text, selectedText) do
local str = textBox.Text
local len_offset = 0
local occurs = {}
repeat
local s, e = string.find(str, selectedText)
if e then
table.insert(occurs, #occurs + 1, {s+len_offset, e+len_offset})
str = string.sub(str, e+1)
len_offset = len_offset + e
end
until (not s)
-- table.insert(matchesPosition, str)
table.insert(matches, m)
end
for i,v in pairs(matches) do
Found = Found + 1
end

if Found >= 1 then
-- Event will happen here.
end
end

textBox:GetPropertyChangedSignal("CursorPosition"):Connect(showSelection)
textBox:GetPropertyChangedSignal("SelectionStart"):Connect(showSelection)