Lua: gmatch multi line string? - lua

I'm trying to make a function that searches through some code to find the line the search term is on, as well as the line's index. The code is a multi line string with new line characters. I was thinking of using gmatch to do this, but I have no clue how.
This is my code at the moment. It's awful, but I can't think of a way to make it any better:
local function search( code, term )
local matches = {}
local i = 0
for line in string.gmatch( code, "[^\r\n]+" ) do
i = i + 1
if string.find( line, term, 1, true ) then
table.insert( matches, { line = i, code = line } )
end
end
return matches
end
Any help would be appreciated!

Your solution seem fine to me. The problem with using a single gmactch loop is your requirement to report line numbers. The code below avoids this by embedding line numbers into the code. I've use # to mark line numbers. You can use any char that does not appear in the source code, even something like \0.
function search(code,term)
for a,b in code:gmatch("#(%d+):([^\n]-"..term.."[^\n]-)\n") do
print(a)
print(b)
end
end
local n=0
code="\n"..code
code=code:gsub("\n", function () n=n+1 return "\n#"..n..":" end)
search(code,"matc")

Related

Lua length of Frame for Parsing

I have an binary file with shows glibberish infos if i open it in Notepad.
I am working on an plugin to use with wireshark.
So my problem is that I need help. I am reading in an File and need to find 'V' '0' '0' '1' (0x56 0x30 0x30 0x31) in the File, because its the start of an Header, with means there is an packet inside. And I need to do this for the whole file, like parsing. Also should start the Frame with V 0 0 1 and not end with it.
I currently have an Code where I am searching for 0x7E and parse it. What I need is the length of the frame. For example V 0 0 1 is found, so the Length from V to the Position before the next V 0 0 1 in the File. So that I can work with the length and add it to an captured length to get the positions, that wireshark can work with.
For example my unperfect Code for working with 0x7E:
local line = file:read()
local len = 0
for c in (line or ''):gmatch ('.') do
len = len + 1
if c:byte() == 0x7E then
break
end
end
if not line then
return false
end
frame.captured_length = len
Here is also the Problem that the Frame ends with 7E which is wrong. I need something that works perfectly for 'V' '0' '0' '1'. Maybe I need to use string.find?
Please help me!
Thats an example how my file looks like if i use the HEX-Editor in Visual Studio Code.
Lua has some neat pattern tools. Here's a summary:
(...) Exports all captured text within () and gives it to us.
-, +, *, ?, "Optional match as little as possible", "Mandatory match as much as possible", "optional match as much as possible", "Optional match only once", respectively.
^ and $: Root to start or end of file, respectively.
We'll be using this universal input and output to test with:
local output = {}
local input = "V001Packet1V001Packet2oooV001aaandweredonehere"
The easiest way to do this is probably to recursively split the string, with one ending at the character before "V", and the other starting at the character after "1". We'll use a pattern which exports the part before and after V001:
local this, next = string.match(input, "(.-)V001(.*)")
print(this,next) --> "", "Packet1V001Packet2..."
Simple enough. Now we need to do it again, and we also need to eliminate the first empty packet, because it's a quirk of the pattern. We can probably just say that any empty this string should not be added:
if this ~= "" then
table.insert(output, this)
end
Now, the last packet will return nil for both this and next, because there will not be another V001 at the end. We can prepare for that by simply adding the last part of the string when the pattern does not match.
All put together:
local function doStep(str)
local this, next = string.match(str, "(.-)V001(.*)")
print(this,next)
if this then
-- There is still more packets left
if this ~= "" then
-- This is an empty packet
table.insert(output, this)
end
if next ~= "" then
-- There is more out there!
doStep(next)
end
else
-- We are the last survivor.
table.insert(output, str)
end
end
Of course, this can be improved, but it should be a good starting point. To prove it works, this script:
doStep(input)
print(table.concat(output, "; "))
prints this:
Packet1; Packet2ooo; aaandweredonehere

Lua table contents separated at equal sign

I am learning Lua, and i want to use it with Rainmeter.
In Rainmeter i use an external txt file to store skin positions with the following type of lines:
pza=A1
pzb=B2
pzc=D3
... (and so on...)
In my Lua script i made an array with reading the lines in it. So the first line is pza=A1, the second is pzb=B2, and so.
Is there any way to check only the value after the equal sign? So separating somehow the pza=A1, to get the "pza" as key, and to get "A1" as value?
Thank you very much for the help in advance!
you can use gmatch and patterns:
local s=[[
pza=A1
pzb=B2
pzc=D3
]]
local t= {}
for k,v in s:gmatch('(%w+)=(%w+)') do
t[k]=v
print(k,t[k])
end
result:
pza A1
pzb B2
pzc D3
I am not sure if I understood but try something like this where line would be the line you read from the file.
local line = "test1=100"
local delim = string.find(line, "=")
key = string.sub(line, 1, delim - 1)
val = string.sub(line, delim + 1, -1)
print("Key: "..key.." Val:"..val)
This will print:
Key: test1 Val:100

Why does the Lua interactive interpreter stop letting me type things in?

I am writing a program to find the standard deviation of a data set. I don't have a proper Lua editor so I am testing everything from the interactive interpreter.
In the code below, everything seems to work until I get to the diffsqrd function. After I call this function, the interpreter stops letting me type anything in. I have to close it and start over again. I have tested this function by itself, without the code before it and it works fine.
I tried saving the whole thing as a .lua file and running it with dofile but it did the same thing.
I get nothing, and then I can no longer type into the interpreter. What is going on?
--a function to see if a file exists
function file_exists(file)
local f=io.open(file, "r")
if f then f:close() end
return f ~= nil
end
--get all lines from a file, returns an empty
--list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
lines = {}
for line in io.lines(file) do
lines[#lines + 1] = line
end
return lines
end
--Put the .rec file into an array
y_positions=lines_from([[Z:\Octupole stuff\programming\y_p_test.rec]])
--functions to find the standard deviation of an array.
--total, average, difference squared. I stop here because this is the
--minimum code required to cause the problem.
function total(a)
local sum=0
for i,v in ipairs(a) do sum = sum + v
end
return sum
end
function average(a)
if #a==0 then mean=0
else mean=total(a)/#a
end
return mean
end
function diffsqrd(a)
local diff={}
for i in ipairs(a) do
diff[i]=(a[i]-average(a))^2
end
return diff
end
--Use the diffsqrd function on the .rec file.
yd=diffsqrd(y_positions)
print(yd[1])

Lua double results showing

So my lua script is showing double results:
It should only show one of each type of fluid.
This is the part of the script :
function firstToUpper(str)
return (str:gsub("^%l", string.upper))
end
function dispTanks()
mon.setCursorPos(offsetPos, 1)
mon2.setCursorPos(offsetPos,1)
for i=1, #machines do
-- RC Tanks --------------------------------------------
if string.find(machines[i], "rcirontankvalvetile")
or string.find(machines[i], "rcsteeltankvalvetile") then
if peripheral.isPresent(machines[i]) then
periph = peripheral.wrap(machines[i])
fluidRaw, fluidName, fluidAmount, fluidCapacity, fluidID = marik.getTank(periph)
if fluidName == nil then
-- does not display empty tanks
elseif fluidName ~= nil then
mon2.setTextColor(tc)
x,y = mon2.getCursorPos()
mon2.setCursorPos(offsetPos, (y+1))
mon2.clearLine()
-- marik.cString(offsetPos,(y+1), tc, right, ",")
nameFL = firstToUpper(marik.comma(fluidName):match("[^.]*"))
mon2.write("Tank (" .. nameFL .. ") : " .. marik.getBuckets(fluidAmount) .. " buckets")
end
end
end
end
end
I though it was not ending the showing with a "," "." or a ")" but that doesn't seem to be the case. How can i fix this?
Pastebin edit
This are the 2 complete codes:
The main program : http://pastebin.com/ejVPwW4Q
The api : http://pastebin.com/uycrzMTy
After taking a look at this i would suggest taking a look into what your table looks like because the code posted above does not seem to have anything wrong with it, BUT if your table some how duplicated the machines then it would certainly print it out twice, that's where i would start to look.
Edit - and by table i mean the "array" machines
Code to debug the table "array" put this before the section of code you placed on your question..
for k, v in pairs(machines) do
print(tostring(k)..": "..tostring(v))
end

Lua multiline comments past ]]'s

I'm trying to find out a way to use a multiline comment on a batch of code, but it keeps mistaking some syntax in it as a ]] and thinking I want it to end there, which I don't!
--[[
for k,v in pairs(t) do
local d = fullToShort[k]
local col = xColours[v[1]] -- It stops here!
cecho(string.format(("<%s>%s ", col, d))
end
--]]
I thought I read somewhere it was possible to do use a different sort of combination to avoid those errors, like --[=[ or whatnot... Could someone help?
As you can see in Strings tutorial there is a special [===[ syntax for nesting square braces. You can use it in block comments too. Just note, that number of = signs must be the same in open and close sequence.
For example 5 equals will work.
--[=====[
for k,v in pairs(t) do
local d = fullToShort[k]
local col = xColours[v[1]] -- It stops here!
cecho(string.format(("<%s>%s ", col, d))
end
--]=====]
You can use the following to create multiline comments past ]]'s:
--[[
codes
]]

Resources