Reputation: 57
Here is my code:
local code = [[
local a = 1
local b = 2
]]
local y = 0
for Paragraph in string.gmatch(code,"[^\n]+") do
print(Paragraph)
for Word in string.gmatch(Paragraph, "[^ ]+") do
end
y = y + 1
end
The problem is pattern doesn't recognize my empty paragraphs how can i fix this ?
If you run the code you will what i mean
Output is:
local a = 1
local b = 2
Instead it should be:
--space
local a = 1
--space
local b = 2
--space
Upvotes: 1
Views: 609
Reputation: 1171
Instead it should be:
--space local a = 1
You won't get that first space because Lua long strings discard the first newline.
Your problem is that your match on "[^\n]+"
matches at least one character which is not a newline. An empty line won't match (there are no characters between the newlines) and thus they don't get shown.
Now you can change that to "[^\n]*"
like this:
for Paragraph in string.gmatch(code,"[^\n]*") do
print("Line=", Paragraph)
for Word in string.gmatch(Paragraph, "[^ ]+") do
print ("Word=", Word)
end
end
But that has a different problem:
Line= local a = 1
Word= local
Word= a
Word= =
Word= 1
Line=
Line=
Line= local b = 2
Word= local
Word= b
Word= =
Word= 2
Line=
Line=
Blank lines appear twice!
A handy function for iterating through a string, a line at a time, is this:
function getlines (str)
local pos = 0
-- the for loop calls this for every iteration
-- returning nil terminates the loop
local function iterator (s)
if not pos then
return nil
end -- end of string, exit loop
local oldpos = pos + 1 -- step past previous newline
pos = string.find (s, "\n", oldpos) -- find next newline
if not pos then -- no more newlines, return rest of string
return string.sub (s, oldpos)
end -- no newline
return string.sub (s, oldpos, pos - 1)
end -- iterator
return iterator, str
end -- getlines
That handles empty lines. Now you can write your code like this (assuming the function above precedes your code):
for Paragraph in getlines (code) do
print("Line=", Paragraph)
for Word in string.gmatch(Paragraph, "[^ ]+") do
print ("Word=", Word)
end
end
Output:
Line= local a = 1
Word= local
Word= a
Word= =
Word= 1
Line=
Line= local b = 2
Word= local
Word= b
Word= =
Word= 2
Line=
You can turn the function getlines
into a Lua module, like this:
getlines.lua
function getlines (str)
local pos = 0
-- the for loop calls this for every iteration
-- returning nil terminates the loop
local function iterator (s)
if not pos then
return nil
end -- end of string, exit loop
local oldpos = pos + 1 -- step past previous newline
pos = string.find (s, "\n", oldpos) -- find next newline
if not pos then -- no more newlines, return rest of string
return string.sub (s, oldpos)
end -- no newline
return string.sub (s, oldpos, pos - 1)
end -- iterator
return iterator, str
end -- getlines
return getlines
Now all you have to do is "require" it:
require "getlines"
for Paragraph in getlines (code) do
print("Line=", Paragraph)
for Word in string.gmatch(Paragraph, "[^ ]+") do
print ("Word=", Word)
end
end
Upvotes: 1
Reputation: 28994
You don't get the empty line because you look for the complement of \n. If you only have \n in your line, there is no complement and you get no match.
You could use this pattern: "[^\n]*\n?" to get what you want. This pattern matches any line. So everything or nothing that is not a \n which is followed by 0 or 1 instances of \n
Upvotes: 1
Reputation: 755
This should do the trick:
local y,code = 0,[[
local a = 123
local b = 456
local c = "too much newlines because we're cool"
]]
local i = 1
-- Why would you start with newlines? Oh well
local sigh = code:match("\n+")
y = y + #sigh
-- debug printing of newlines
for i=1,y do print() end
while true do
local start,stop = code:find("[^\n]+",i)
if not start then break end
local Paragraph = code:sub(start,stop)
-- Do your Paragraph parsing and stuff
print("PARAGRAPH:",Paragraph)
start,stop = code:find("\n+",stop+1)
if not stop then break end
y,i = y + stop - start + 1,stop+1
-- printing newlines to get the desired effect in output
for i=2,stop-start+1 do print() end
-- starting from 2 since the print(code:sub(...)) already prints one \n
end
-- reached end of the string
It gives you this nice output:
PARAGRAPH: local a = 123
PARAGRAPH: local b = 456
PARAGRAPH: local c = "too much newlines because we're cool"
Tested at http://www.lua.org/cgi-bin/demo
Upvotes: 0