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
Related
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
I see several posts about making a string in to a lua table, but my problem is a little different [I think] because there is an additional dimension to the table.
I have a table of tables saved as a file [i have no issue reading the file to a string].
let's say we start from this point:
local tot = "{{1,2,3}, {4,5,6}}"
When I try the answers from other users I end up with:
local OneDtable = {"{1,2,3}, {4,5,6}"}
This is not what i want.
how can i properly create a table, that contains those tables as entries?
Desired result:
TwoDtable = {{1,2,3}, {4,5,6}}
Thanks in advance
You can use the load function to read the content of your string as Lua code.
local myArray = "{{1,2,3}, {4,5,6}}"
local convert = "myTable = " .. myArray
local convertFunction = load(convert)
convertFunction()
print(myTable[1][1])
Now, myTable has the values in a 2-dimensional array.
For a quick solution I suggest going with the load hack, but be aware that this only works if your code happens to be formatted as a Lua table already. Otherwise, you'd have to parse the string yourself.
For example, you could try using lpeg to build a recursive parser. I built something very similar a while ago:
local lpeg = require 'lpeg'
local name = lpeg.R('az')^1 / '\0'
local space = lpeg.S('\t ')^1
local function compile_tuple(...)
return string.char(select('#', ...)) .. table.concat{...}
end
local expression = lpeg.P {
'e';
e = name + lpeg.V 't';
t = '(' * ((lpeg.V 'e' * ',' * space)^0 * lpeg.V 'e') / compile_tuple * ')';
}
local compiled = expression:match '(foo, (a, b), bar)'
print(compiled:byte(1, -1))
Its purpose is to parse things in quotes like the example string (foo, (a, b), bar) and turn it into a binary string describing the structure; most of that happens in the compile_tuple function though, so it should be easy to modify it to do what you want.
What you'd have to adapt:
change name for number (and change the pattern accordingly to lpeg.R('09')^1, without the / '\0')
change the compile_tuple function to a build_table function (local function build_tanle(...) return {...} end should do the trick)
Try it out and see if something else needs to be changed; I might have missed something.
You can read the lpeg manual here if you're curious about how this stuff works.
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")
Could someone help me with this?
I can not make the variable "v" receive any characters while the variable "k" receives only alphanumeric.
t = {}
for k, v in string.gmatch(decrypt, "(%w+)=([^']*)") do
t[k] = v
print(k,v)
end
I have a file with the following content:
email=mbw#iue.com
ip=192.168.100.1
mac=af:45:t6:45:67
(maybe oversimplifying, if so, sorry...)
If you are trying to break the lines in your file at the '=' an assign them as key, value pairs in t:
--
-- PART I - read from a file
--
local file = "pattern.dat" -- our data file
local t = {} -- hold file values
for l in io.lines(file) do -- get one line at a time
local k, v = string.match(l, "(.+)=(.+)") -- key, value delimited by '=''
t[k] = v -- save in table
print(k,t[k])
end
print("\n\n")
--
-- PART II - read from data string
--
local data = "email=mbw#iue.com/ip=192.168.100.1/mac=af:45:t6:45:67"
data = data .. "/" -- need a trailing '/'
t = {} -- hold data values
for l in string.gmatch(data, "(.-)/") do -- get one 'line' at a time
local k,v = string.match(l, "(.+)=(.+)") -- key, value delimited by '=''
t[k] = v
print(k,t[k])
end
NOTE about the "^" anchor (from reference manual entry for 'gmatch'):
For this function, a caret '^' at the start of a pattern does not work as an anchor, as this would prevent the iteration.
http://www.lua.org/manual/5.3/manual.html#pdf-string.gmatch
You are actually only getting one match because * is greedy. If you are trying to split lines, try (%w+)=([^'\n]*)\n
Note: Lua uses patterns, not regular expressions. Sometimes the difference is unimportant, sometimes vital.
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
]]