another problem with string pattern

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Kavaline
Prole
Posts: 8
Joined: Sun Jun 27, 2021 5:19 pm

another problem with string pattern

Post by Kavaline »

Hi, I need help to find the pattern that have the wanted print output:

Code: Select all

str = "(1, 'test', none, 10, '', , 'hi, this is a default bio. change it (asap)!')"
for inf = 1, 9 do
	pat = "%(" .. string.rep("%s?'?.-'?[,%)]+", inf - 1) .. "%s?'?(.-)'?[,%)]+"
	result = str:match(pat)
	print(result, "#" .. inf)
end
--Print result must be:
--1
--test
--none
--10
--
-- or nil
--hi, this is a default bio. change it (asap)!
--nil
--nil
The actual print result is:
1 #1
test #2
none #3
10 #4
#5
#6
hi #7
this is a default bio. change it (asap #8
! #9

I can't find a solution that if found a starting "'", ignores all rules until find a closing "'" and match a right pattern (a ", " or ")$")
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: another problem with string pattern

Post by ReFreezed »

You cannot do this with a single pattern. You need different patterns for matching quoted and unquoted values. This also means you have to match one item at a time and choose the appropriate pattern dynamically.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Kavaline
Prole
Posts: 8
Joined: Sun Jun 27, 2021 5:19 pm

Re: another problem with string pattern

Post by Kavaline »

Ouch.. So, I'm thinking in something with another loop inside, counting the quotes to choose what pattern add to 'pat', I will scratch it later
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: another problem with string pattern

Post by ReFreezed »

No inner loops, counting of quotes, or generation of any pattern needed.

Code: Select all

local str = "(1, 'test', none, 10, '', , 'hi, this is a default bio. change it (asap)!')"

local items = {}
local pos   = str:match("%(%s*()") or error("missing '('")

while true do
	-- Match item.
	local item
	if str:sub(pos, pos) == "'" then
		item, pos = str:match("^'(.-)'%s*()", pos) -- Quoted value.
		assert(item, "missing end quote")
	else
		item, pos = str:match("^([^,)]*)()", pos) -- Unquoted value.
		item      = item:gsub("%s+$", "") -- Trim trailing spaces.
	end

	table.insert(items, item)

	-- Continue or stop.
	if str:sub(pos, pos) == "," then
		pos = str:match("^,%s*()", pos) -- Continue loop.
	elseif str:sub(pos, pos) == ")" then
		break -- End of items.
	else
		error("expected ',' or ')' at position "..pos)
	end
end

for i, item in ipairs(items) do
	print("#"..i.." '"..item.."'")
end

--[[ Output:
#1 '1'
#2 'test'
#3 'none'
#4 '10'
#5 ''
#6 ''
#7 'hi, this is a default bio. change it (asap)!'
]]
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Kavaline
Prole
Posts: 8
Joined: Sun Jun 27, 2021 5:19 pm

Re: another problem with string pattern

Post by Kavaline »

But thanks to your direction, I did with them xD
Also, I will check your solution too, I didn't realize that I could use the () to get a string position, I tried something like this, but walked on other way because I couldn't find how to get the right positions. The way was, break the string after every match...

Code: Select all

str = "(1, 'test', none, 10, '', , 'hi, this is a default bio. change it (asap)!')"
s = str
result = {}
for inf = 1, 9 do
	s = string.sub(s or "", math.min(2,s:len()))
	if s:match("^'") then
		result[inf] = s:match("%s?'(.-)'[,%)]+")
	else
		result[inf] = s:match("%s?(.-)[,%)]+")
	end
	s = s:match("^'?" .. string.rep(".", string.len(result[inf] or "")) .. "'?.?(.+)")
	print(result[inf], "#" .. inf)
end
The only problem is that I can't get the exact info that I want; on my first try, I could get a Nth info directly, without a loop (thanks to string.rep). In this solutions, I always will read all infos in a loop, and after, get the one that I want. But if is the fastest way (and less headache), is this
Rigachupe
Party member
Posts: 100
Joined: Fri Jun 18, 2021 11:21 am

Re: another problem with string pattern

Post by Rigachupe »

Or use a JSON library. The input string would change to:
local str = "{1, 'test', none, 10, '', , 'hi, this is a default bio. change it (asap)!'}"

And the output from JSON would be a table that you can traverse like an array.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 1 guest