Lua - Reflection - Get list of functions/fields on an object? - c++
I'm new to Lua and dealing with Lua as a scripting language in an alpha release of a program. The developer is unresponsive and I need to get a list of functions provided by some C++ objects which are accessible from the Lua code.
Is there any easy way to see what fields and functions these objects expose?
In Lua, to view the members of a object, you can use:
for key,value in pairs(o) do
print("found member " .. key);
end
Unfortunately I don't know if this will work for objects imported from C++.
If allowed in the environment, looking at the metatable of the exported C++ object can help:
for key,value in pairs(getmetatable(o)) do
print(key, value)
end
Print all the globals:
-- globals.lua
-- show all global variables
local seen={}
function dump(t,i)
seen[t]=true
local s={}
local n=0
for k in pairs(t) do
n=n+1 s[n]=k
end
table.sort(s)
for k,v in ipairs(s) do
print(i,v)
v=t[v]
if type(v)=="table" and not seen[v] then
dump(v,i.."\t")
end
end
end
dump(_G,"")
source: http://www.lua.org/cgi-bin/demo
Output:
_G
_VERSION
assert
bit32
arshift
band
bnot
bor
btest
bxor
extract
lrotate
lshift
replace
rrotate
rshift
collectgarbage
coroutine
create
isyieldable
resume
running
status
wrap
yield
debug
gethook
getinfo
getlocal
getmetatable
getupvalue
getuservalue
sethook
setlocal
setmetatable
setupvalue
setuservalue
traceback
upvalueid
upvaluejoin
dump
error
getmetatable
io
write
ipairs
load
math
abs
acos
asin
atan
atan2
ceil
cos
cosh
deg
exp
floor
fmod
frexp
huge
ldexp
log
log10
max
maxinteger
min
mininteger
modf
pi
pow
rad
random
randomseed
sin
sinh
sqrt
tan
tanh
tointeger
type
ult
next
os
clock
date
difftime
exit
setlocale
time
pairs
pcall
print
rawequal
rawget
rawlen
rawset
select
setmetatable
string
byte
char
dump
find
format
gmatch
gsub
len
lower
match
pack
packsize
rep
reverse
sub
unpack
upper
table
concat
insert
move
pack
remove
sort
unpack
tonumber
tostring
type
utf8
char
charpattern
codepoint
codes
len
offset
xpcall
Something along the same vein as the answer Mr Stinky gave but a whole lot more information.
I made the below code originally for a running from a web server but have added the capability to run on lua for windows
on a web server options are passed in query string ?loadmodules=no&module=_G
in program form options are passed on command line functs loadmodules no module _G
if run with no arguments all modules in pkgpath are loaded and parsed
#!/usr/bin/lua
--------------------------------------------------------------------
--|Functs.lua load available modules parse tables give write to HTML|
--|Table Of Contents, modules, available functions, strings etc.. |
--------------------------------------------------------------------
-- CONFIGURE----------------------------------------------------------------------------------------
local sPkgPath = "/usr/lib/lua" --look here for modules to load in addition to the intrinsic ones
local sWpkgPath = "C:\\Program Files (x86)\\Lua\\5.1\\lua\\" --package path for windows
local sURLsearch = "http://pgl.yoyo.org/luai/i/" --for lua standard functions search this site
local iMaxStr = 1024 -- maximum characters in a string printed to HTML table
local sFileOut = "functs.html"
----------------------------------------------------------------------------------------------------
local tQuery = {} --key,val pairs of arguments
local sQuery = "" --string of arguments ex:'?modload=no&module=_G.math...'
local sResults = "" --Results of each step through
local sEnv = "web" --running on a web server?
----------------------------------------------------------------------------------------------------
----------------------------FUNCTIONS START----------------------------------------------
local function a2m_m2a(addr_member)
--turns members into addresses; addresses back into members
return addr_member
end
local function PrRes(sVal)
--cats results strings
sResults = sResults .. sVal
end
local function errorHandler( err )
PrRes(" ERROR:" .. err .. " ")
--print(debug.traceback())
end
local function putOutput(tData, iCt)
--keys are integer indices, values to iCt written, if iCt = nil whole table written
for k, v in ipairs(tData) do
if iCt == nil or k <= iCt then
io.write (v) --write to std out could be changed here, or as below we change stdout file
end
end
end
local function parse_url(s)
--http://www.flashair-developers.com/en/support/forum/#/discussion/880/getting-query-string-parameters-from-an-http-request-in-lua/
--splits on '=' and '&' puts argument string into named keys with value [Key1] = (val1)&[Key2] = (val2)
--ex: Key1=va1&Key2=val2
local ans = {[0]=""}
----FUNCTIONS for parse_url -----------------------------------------------------
local function decode(s)
s = s:gsub('+', ' ')
s = s:gsub('%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end)
return s
end
----END FUNCTIONS for parse_url --------------------------------------------------
if s == nil then return ans end
--s = s:match('%s+(.+)')
for k,v in s:gmatch('([^&=]+)=([^&=]*)&?' ) do
--2 capture groups all chars (not '&' or '=') '=' all chars (not '&' or '=') followed by '' or '&' or '?'
ans[ k ] = decode(v)
end
return ans
end
local function tableByName(tName)
--find the longest match possible to an actual table
--Name comes in as (table) tName.var so we can pass back out the name found PITA
--returns the table found (key and value)
local ld = {}
local sMatch = ""
local kMatch = nil
local vMatch = nil
----FUNCTIONS for tableByName -----------------------------------------------------
local function search4Str(n, k, v)
local sKey = tostring(k)
if string.find (n, sKey,1,true) then
if sKey:len() > sMatch:len() then sMatch = sKey kMatch = k vMatch = v end
--find the longest match we can
end
end
----END FUNCTIONS for tableByName -------------------------------------------------
if tName.val ~= nil and tName.val ~= "" then
for k, v in pairs(_G) do --_G check both since some tables are only in _G or package.loaded
search4Str(tName.val, k, v)
end
for k, v in pairs(package.loaded) do --package.loaded
search4Str(tName.val, k, v)
end
if not string.find (sMatch, "_G",1,true) then sMatch = "_G." .. sMatch end -- put the root _G in if not exist
if kMatch and vMatch then ld[kMatch] = vMatch tName.val = sMatch return ld end
end
tName.val = "_G"
return package.loaded --Not Found return default
end
local function get_common_branches(t, tRet)
--load t 'names(values)' into keys
--strip off long paths then iterate value if it exists
--local tRet={}
local sBranch = ""
local tName
for k in pairs(t) do
tName={["val"]=k}
tableByName(tName)
sBranch = tName.val
if tRet[sBranch] == nil then
tRet[sBranch] = 1 --first instance of this branch
else
tRet[sBranch] = tRet[sBranch] + 1
end
end
end
local function pairsByPairs (t, tkSorted)
--tkSorted should be an already sorted (i)table with t[keys] in the values
--https://www.lua.org/pil/19.3.html
--!!Note: table sort default function does not like numbers as [KEY]!!
--see *sortbyKeys*cmp_alphanum*
--for n in pairs(t) do table.insert(kSorted, n) end
--table.sort(kSorted, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if tkSorted[i] == nil then return nil
else return tkSorted[i], t[tkSorted[i]]
end
end
return iter
end
local function sortbyKeys(t, tkSorted)
--loads keys of (t) into values of tkSorted
--and then sorts them
--tkSorted has integer keys (see ipairs)
----FUNCTIONS for sortByKeys -------------
local cmp_alphanum = function (op1, op2)
local type1= type(op1)
local type2 = type(op2)
if type1 ~= type2 then
return type1 < type2
else
return op1 < op2
end
end
----END FUNCTIONS for sortByKeys ---------
for n in pairs(t) do table.insert(tkSorted, n) end
table.sort(tkSorted, cmp_alphanum)--table.sort(tkSorted)
end
local function load_modules(sPkgRoot, sWinPkgRoot)
--attempt to load all found modules
--Modules may depend on other modules
--Supresses print, os.exit, rawset
--Ignores *.luac
PrRes("Functions Suspended, ")
local orig ={osexit = _G.os.exit, print = _G.print, rawset = _G.rawset} --save original functions for later restoration
_G.rawset = function(t, i, v) --orig.print ("rawset!")
if _G[i] == v then
orig.rawset(t,i,"_G["..tostring(i).."] !DUP!") --Don't allow global table to be copied
else
orig.rawset(t,i,v)
end
end
_G.os.exit = function() error(999) end --don't exit whole program just this function
_G.print = function()end --don't print
local st = io.popen("find "..sPkgRoot.." -type f -iname '*.so' -o -type f -iname '*.lua'" .." 2> nul")
if not st:read(0) then --find didn't work try windows dir instead
st = io.popen("dir /b /s " .."\""..sWinPkgRoot.."\\*.lua\" " .. "\""..sWinPkgRoot.."\\*.so\" " ) --simple output, subdir
end
if st:read(0) then
for module in st:lines() do
if (module) then
if not string.find (module, ".luac", 1, true) then --don't load precompiled code
local ok, res = pcall(loadfile(module))--protected call
end
end
end
end
_G.os.exit = orig.osexit
_G.print = orig.print
_G.rawset = orig.rawset
PrRes("Functions Restored, ")
end
local function dtTag(sType)
--convert named type; 'number'.. to short type '[n]...'
--if '?' supplied print out datatype key; number = [n]...
local retType = "?"
local typ = {
["nil"] = "nil",
["boolean"] = "b",
["number"] = "n",
["string"] = "s",
["userdata"] = "u",
["function"] = "f",
["thread"] = "thr",
["table"] = "t"
}
if sType == "?" then retType = "Datatypes: " end
for k,v in pairs(typ) do
if sType == k then
retType = v break
elseif (sType == "?") then
retType = retType .. " [" ..v.. "] = " .. k
end
end
return " [" ..retType.. "] "
end
local function dump_Tables(tBase,sFunc, tSeen, tRet)
--Based on: http://www.lua.org/cgi-bin/demo?globals
--Recurse through tBase tables copying all found Tables
local sSep=""
local ld={}
if sFunc ~= "" then sSep = "." end
for k, v in pairs(tBase) do
k = tostring(k)
if k ~= "loaded" and type(v) == "table" and not tSeen[v] then
tSeen[v]=sFunc
tRet[sFunc..sSep .. k] = a2m_m2a(v) --place all keys into ld[i]=value
dump_Tables(v, sFunc .. sSep .. k, tSeen, tRet)
end
end
--print("tables dumped")
end
local function dump_Functions(tBase)
--Based on: http://www.lua.org/cgi-bin/demo?globals
--We already recursed through tBase copying all found tables
--we look up the table by name and then (ab)use a2m_m2a() to load the address
--after finding the table by address in tBase we will put the table address of tFuncs in its place
for k,v in pairs(tBase) do
local tTable = a2m_m2a(v)
local tFuncs = {}
--print(type(tTable))
for key, val in pairs(tTable) do
if key ~= "loaded" then
tFuncs[dtTag(type(val)) .. tostring(key) ]= val --put the name and value in our tFuncs table
end
end
tBase[k] = a2m_m2a(tFuncs) -- copy the address back to tBase
end
--print("functions dumped")
end
local function html_Table(tBase, tkSorted, sId, fHeader, sTitle, iCols, fCellCond, fCell, fFooter, fOut)
--[[Prints HTML <table>
tBase, the table of items you want in your table [key] contains the cell data
tkSorted, the key sorted values of tBase (tkSorted keys are (i) based (see: ipairs)
sID, ID of div tag
fHeader, function returning <DIV></DIV>
sTitle, title of the table
iCols, number of cells wide
fCellCond, if return (TRUE) cell is displayed, fCellCond(k, v, n, iCells, i)
fCell, function returning contents of cell
fFooter, function returning tags at the end of the </table>
fOut, function to print the table[integer]=HTML_DATA based output
--]]
local oTbl={}
local i = 1
local strName=""
local iCells = 0
local n = 0 --counts columns
oTbl[i]=fHeader(sId,sTitle)
i = i + 1 oTbl[i] = "<table><tr><th colspan='"..iCols.."'>"..sTitle.."</th></tr>\r\n"
for k, v in pairsByPairs(tBase,tkSorted ) do
strName= tostring(k)
if fCellCond(k, v, n, iCells, i) then
if n == 0 then
i = i + 1 oTbl[i] = "\t<tr>\r\n"
end
n = n + 1 i = i + 1 iCells = iCells + 1
oTbl[i] = "\t\t"..fCell(strName, v, sTitle).."\r\n"
if n >= iCols then
n = 0
i = i + 1
oTbl[i] = "\t</tr>\r\n"
end
fOut(oTbl, i)
i = 0
end
end
if n ~= 0 then
i = i + 1 oTbl[i] = "\t</tr>\r\n"
end
i = i + 1 oTbl[i] = "</table>\r\n" .. fFooter(strName)
fOut(oTbl, i)
return iCells
end
local function html_function_tables(tBase, tkSortTbase, fOut, iCols)
--print a table of functions for every module in tBase
local strName=""
local iCt = 0
local tFuncs = {}
local tkSorted = {}
----FUNCTIONS for Funct Html-----------------------------------------------------
local function fCellTrue(k)
--return tostring(k) == strName
return true
end
local function fTableCell(strName, value, sTitle)
local sHref = ""
local sType = type(value)
local sPkg = string.match (sTitle, ".+%p(%a+%P)")
local sVal = ""
--strName = tostring(strName)
if string.len(strName) > iMaxStr then
strName=string.sub(strName,1 , iMaxStr).."....." --Truncate strings longer than iMaxStr
end
if sPkg ~= nil and string.find (";debug;package;string;coroutine;io;math;os;table;", ";"..sPkg..";") then
sHref = "<a href='"..sURLsearch .. string.sub(strName,6) .. "'>?</a>" --remove [f] from beginning
end
if nil ~= string.find (";string;number;userdata;boolean;", sType, 1, true) then
sVal = tostring(value)
if string.len(sVal) > iMaxStr then
sVal=string.sub(sVal,1 , iMaxStr).."....." --Truncate strings longer than iMaxStr
end
return "</tr><td colspan='"..iCols.."'>".. sHref ..strName.." : "..sVal.."</td><tr>"
else
return "<td><a>"..strName.."</a>".. sHref .. "</td>"
end
end
local function fPageAnchor(sId, strTitle)
local sHref = ""
local sAddr = ""
local sModload = tQuery.modload
if not sModload then sModload = "" end
local sStyle = "'style='display:block;text-decoration: none"
if os.getenv("SERVER_NAME") and os.getenv("SCRIPT_NAME") then
sAddr = "http://"..os.getenv("SERVER_NAME") .."/".. os.getenv("SCRIPT_NAME") .."?modload=".. sModload
sHref="<a href='"..sAddr.."&module="..strTitle..sStyle.."'>" .."Module: " .. strTitle.. "</a>"
else
sHref = "Module: " .. strTitle
end
return "<div id='"..sId.."'style='color:#0000FF'><h3>"..sHref.."</h3></div>\r\n"
end
local function fPageFooter(strName)
return "<p><a href='#toc'>^</a></p><BR /><BR />"
end
----END FUNCTIONS for Funct Html--------------------------------------------------
for key, val in pairsByPairs(tBase, tkSortTbase) do
strName=tostring(key)
tkSorted = {}
tFuncs = a2m_m2a(val)
sortbyKeys(tFuncs, tkSorted)
iCt = iCt + html_Table(tFuncs,tkSorted, strName, fPageAnchor, strName, iCols, fCellTrue, fTableCell, fPageFooter, fOut)
end
return iCt
end
local function html_toc_tables(tBase, tkSortTbase, fOut, iCols)
local iCt = 0
----FUNCTIONS for TOC Html-----------------------------------------------------
local function fTableCell(strName)
return "<td><a href='#" .. strName .. "'style='display:block;text-decoration: none'>" .. strName.. "</a></td>"
end
local function fCellTrue()
return true
end
local function fFooter()
return "<BR /><b>" .. dtTag("?") .. "</b><BR /><BR /><BR /><BR /><BR /><BR />"
end
local function fPageAnchor(sId, strTitle)
return "<div id='"..sId.."'><p></p></div>\r\n"
end
----END FUNCTIONS for TOC Html--------------------------------------------------
iCt = html_Table(tBase, tkSortTbase, "toc", fPageAnchor, "* Modules Found * Lua Ver. ".._VERSION, iCols, fCellTrue, fTableCell, fFooter, fOut)
return iCt
end
local function main (sPackage)
local tSeen= {}
local tcBase = {}
local tkSortCbase = {}
local tMods= {}
local tkSortMods = {}
local iCtF = 0
if not sPackage then sPackage = "_G" end
putOutput( { --header for html document
[1] = "<!DOCTYPE html>\r\n<html><head>\r\n<style>\r\n",
[2] = "\ttable, th, td {border: 1px solid black;}\r\n",
[3] = "\ttable tr:nth-child(even) {background-color: #C4C4C4;}\r\n",
[4] = "\ttable tr:nth-child(odd) {background-color:#EFEFEF;}\r\n",
[5] = "</style>\r\n</head><body>\r\n"
} )
PrRes("Dump Tables: ")
xpcall( function()dump_Tables(tableByName({["val"] = sPackage}),"", tSeen, tMods) end , errorHandler )
tSeen = nil
PrRes("ok, ")
PrRes("Dump Functions: ")
xpcall( function()dump_Functions(tMods)end , errorHandler )
PrRes("ok, ")
PrRes("Common Branches: ")
get_common_branches(tMods, tcBase)
PrRes("ok, ")
PrRes("Sorting Branches: ")
sortbyKeys(tcBase, tkSortCbase)
sortbyKeys(tMods, tkSortMods)
PrRes("ok, ")
PrRes("Print TOC: ")
iCtF = html_toc_tables(tcBase, tkSortCbase, putOutput, 3)
tcBase= nil tkSortCbase= nil
PrRes(iCtF .." ok, ")
PrRes("Print Functions: ")
iCtF = html_function_tables(tMods, tkSortMods, putOutput, 6)
PrRes(iCtF .." ok, ")
end
----------------------------FUNCTIONS END--------------------------------------------------
if os.getenv("SERVER_NAME") == nil then
sEnv="other"
else --sEnv == web
--Send response header as soon as we load
io.write ("Status: 200 OK\r\nKeep-Alive: timeout=60\r\nContent-Type:text/html\r\nLast-Modified:Sun, 11 Jan 2099 01:01:99 GMT\r\n\r\n") -- end of response)
end
if sQuery == "" then --load arguments from query string if web; or arg[] if not
if sEnv == "web" then
sQuery = os.getenv("QUERY_STRING")
else --Load arguments from arg[] list arg[1]=arg[2]&arg[3]=arg[4]&..
for k,v in pairs({...}) do
sQuery = sQuery .. v
if math.fmod (k, 2) == 0 then
sQuery = sQuery .. "&"
else
sQuery = sQuery .. "="
end
end
end
end
tQuery = parse_url(sQuery)
--[[print(sQuery)
for k,v in pairs(tQuery) do
print ("[", k ,"]=", v)
end]]
if sQuery ~= "modloadno" and tQuery.modload ~= "no" then
PrRes("Load Modules: ")
xpcall( function()load_modules(sPkgPath,sWpkgPath)end, errorHandler )
--load_modules(sPkgPath)
PrRes("ok, ")
end
PrRes("Main; ")
if sEnv ~= "web" then
print("Fileout: " .. sFileOut)
io.output(sFileOut)
end
local ok, res = pcall(main,tQuery.module)
if not ok then
if sEnv ~= "web" then
print("Status: 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\n" .. res .. "\r\n")
else
print("Error: " .. res)
end
end
PrRes("DONE")
io.write("<p> Query: " .. sQuery .. ";; " .. sResults .."</p>")
Sample Output
Related
Excluding SID's and certain columns in Power BI rename script
I'm trying to relabel a bunch of Power BI reports and I am doing that with this script. (Source) => let res = List.Accumulate( Text.ToList(Source), [result="", index=0, source=Source], fnAccumulator ), IsUpper = (txt) => txt <> "" and txt = Text.Upper(txt) and txt <> Text.Lower(txt), fnAccumulator = (state as record, current as text) as record => let prevCharacter = if state[index]=0 then "" else Text.At(state[source], state[index] - 1), prevCharacter2 = if state[index]<=1 then "" else Text.At(state[source], state[index] - 2), nextCharacter = if state[index] = Text.Length(state[source]) - 1 then "" else Text.At(state[source], state[index] + 1), aggregatedResult = if state[index]=0 or current = "" then current else if IsUpper(current) and (not IsUpper(prevCharacter) or (IsUpper(prevCharacter2) and not IsUpper(nextCharacter))) then state[result] & " " & current else state[result] & current, resultRecord = if aggregatedResult = null then null else [result = aggregatedResult, index = state[index]+1, source = state[source]] in resultRecord in res[result] The problem is after running this on every table and applying the changes all the relationships in the report end up nuked. Before After My thought process is that because my script isn't taking into account SID's and renaming those when they should stay the same this is breaking the relationships. Would appreciate either an alternative way of mass renaming these columns or if there is a way to add an exclusion statement into my script that will ignore any and all SIDs
How to parse an url and get query parameters in lua? [duplicate]
I have a URL and would like to parse its Parameter out of it, like: function unescape (s) s = string.gsub(s, "+", " ") s = string.gsub(s, "%%(%x%x)", function (h) return string.char(tonumber(h, 16)) end) return s end function parseurl (s,param) for k, v in string.gmatch( s, "([^&=?]+)=([^&=?]+)" ) do --t[k] = v if k == param then --print (k.." "..v) return unescape(v) end end s = "http://www.page.com/link.php uname=Hans+Testmann&uemail=myemail%40gmail.com&utext=Now+this+is+working+great.%0D%0A++&mdt=1#&mydays:themeupload"s Than I would call it and get Results like after --> parseurl (s, "uname") --> "Hans Testmann" parseurl (s, "uemail") --> "myemail#gmail.com" parseurl (s, "utext") --> "Now this is working great" I already fixed a lot and seems to work, but could you look how its possible to improve?
I would return all parameters in a table and use like so: function urldecode(s) s = s:gsub('+', ' ') :gsub('%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) return s end function parseurl(s) s = s:match('%s+(.+)') local ans = {} for k,v in s:gmatch('([^&=?]-)=([^&=?]+)' ) do ans[ k ] = urldecode(v) end return ans end t = parseurl(s) print(t.uname ) --> 'Hans Testmann' print(t.uemail) --> 'myemail#gmail.com' print(t.utext ) --> 'Now this is working great'
If statement conditions not met, code still executing
I'm writing a VBScript that searches the Active Directory for a computer object. If the object does not exist or exists and is in the correct OU, then it should run a separate script that creates/joins the computer to the AD. ObjExist_CorrectOU_7 = Null ObjExist_CorrectOU_10 = Null If compare = True Then Win7_OU = "OU=DisallowRDP,OU=64Bit,OU=Win8" Win10_OU = "OU=DisallowRDP,OU=64Bit,OU=Win10" For x = 16 To 46 If Asc(Mid(objRS.Fields("distinguishedName"), x, 1)) = Asc(Mid(Win7_OU, (x - 15), 1)) Then ObjExist_CorrectOU_7 = True Else ObjExist_CorrectOU_7 = False End If Next For y = 16 To 46 If Asc(Mid(objRS.Fields("distinguishedName"), y, 1)) = Asc(Mid(Win10_OU, (y - 15), 1)) Then ObjExist_CorrectOU_10 = True Else ObjExist_CorrectOU_10 = False End If Next End If If ObjExist_CorrectOU_7 = True Then WScript.Echo "TRUE" End If Dim objShell Set objShell = WScript.CreateObject("WScript.Shell") filename = "C:\programdata\dell\kace\k2000_deployment_info.conf" Win7_Deployment = "deployment_name=Windows 7 x64 with SP1, join AD" Win10_Deployment = "deployment_name=Development Windows 10 (x64), join AD" Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.OpenTextFile(filename) Do While Not f.AtEndOfStream If ((f.ReadLine = Win7_Deployment) Or ((f.ReadLine = Win7_Deployment) And (ObjExist_CorrectOU_7 = True))) Then WScript.Echo "IT WORKED!" 'objShell.Run "JoinAD_Win7.vbs" Exit Do End If On Error Resume Next Loop f.Close Set g = fso.OpenTextFile(filename) Do While Not f.AtEndOfStream If ((g.ReadLine = Win10_Deployment) Or ((g.ReadLine = Win10_Deployment) And (ObjExist_CorrectOU_10 = True))) Then 'objShell.Run "JoinAD_Win10.vbs" WScript.Echo "IT WORKED AGAIN!" Exit Do End If On Error Resume Next Loop g.Close Set objShell = Nothing The problem I'm running into is that the two If..Then statements execute every time, even though I know the conditions are absolutely NOT being met. Does it have to do with my use of Or and And?
Your question does not satisfy Minimal, Complete, and Verifiable example criteria. However, at first sight: read On Error Statement and ReadLine Method and Working with Files documentation. Do While Not f.AtEndOfStream ''' ↓ this `ReadLine` reads every uneven line i.e. the 1st, 3rd, 5th, … If ((f.ReadLine = Win7_Deployment) Or ((f.ReadLine = Win7_Deployment) And (ObjExist_CorrectOU_7 = True))) Then ''' this one reads every even line ↑ i.e. the 2nd, 4th, 6th, … WScript.Echo "IT WORKED!" 'objShell.Run "JoinAD_Win7.vbs" Exit Do End If On Error Resume Next ' this causes that script continues on line next to IF … THEN ' in case of uneven records in file. ' i.e. runtimme error "Input past end of file" Loop Use something like Do While Not f.AtEndOfStream sReadLine = f.ReadLine If ((sReadLine = Win7_Deployment) Or ((sReadLine = Win7_Deployment) And (ObjExist_CorrectOU_7 = True))) Then WScript.Echo "IT WORKED!" 'objShell.Run "JoinAD_Win7.vbs" Exit Do End If ''' get rid of `On Error Resume Next` statement at all Loop And what about Do While Not f.AtEndOfStream followed up by g.ReadLine? Use either f or g (the same TextStream object in both)…
Targeting a specific occurence in a string and replacing it
I have a string with multiple / in it and I am trying to convert this string in to LaTeX code. Basically (a)/(b) becomes \\dfrac{a}{b}. The difficulty is that (a) and/or (b) could contain other /. To respect the parentheses balancing, I would like to replace the / from left to right, and replacing them accordingly to what it around. I made a try but I don't know how target a specific / and replace. using position and length parameters seems to be very complicated. function ToFrac (s) while s:find ("/") ~= nil do -- Replace : \dfrac{}{}/() -> \dfrac{\dfrac...}{} if ( s:find ( '\\dfrac%b{}%b{}/%b()' , j ) ~= nil ) then x,y,num,den = s:find( '(\\dfrac%b{}%b{})/(%b())' ) den = den:gsub( '.(.+).' , '%1' ) s = s:gsub( '(\\dfrac%b{}%b{})/(%b())', "\\dfrac{"..num.."}{"..den.."}" , 1 ) end print ('### -- ', s) -- Replace : ()/\dfrac{}{} -> \dfrac[}]{\dfrac...} if ( s:find ( '(%b()/\\dfrac%b{}%b{}' ) ~= nil ) then x,y,num,den = s:find( '((%b())/(\\dfrac%b{}%b{})' ) num = num:gsub( '.(.+).' , '%1' ) s = s:gsub( '((%b())/()\\dfrac%b{}%b{})', "\\dfrac{"..num.."}{"..den.."}" , 1 ) end print ('### -- ', s) -- Replace : ()/() -> \dfrac{}{} if ( s:find ( '%b()/%b()' , 1 ) ~= nil ) then x,y,num,den = s:find( '(%b())/(%b())' ) num = num:gsub( '.(.+).' , '%1' ) den = den:gsub( '.(.+).' , '%1' ) s = s:gsub( '(%b())/(%b())', "\\dfrac{"..num.."}{"..den.."}" , 1 ) Done = true end print ('### -- ', s) end -- while return (s) end s = "((a)/(b))/(c)" print (s, ToFrac(s)) s = "(a)/((b)/(c))" print (s, ToFrac(s)) s = "(a)/(b)/(c)/(d))" print (s, ToFrac(s)) s = "((a)/(b))/((c)/(d))" print (s, ToFrac(s))
Amended version of rpattiso's idea: function to_frac(expr) local t return expr == '' and '' or (expr..'()'):gsub('(.-)(%b())', function(prefix, subexpr) local replace_with = '' if not prefix:find'^%s*/%s*$' then t, replace_with = {}, (not t and '' or t[2] and '\\dfrac{'..t[1]..'}{'..t[2]..'}' or '('..t[1]..')')..prefix elseif t[2] then t = {'\\dfrac{'..t[1]..'}{'..t[2]..'}'} end table.insert(t, to_frac(subexpr:sub(2,-2))) return replace_with end ) end print(to_frac' (a )/((b) / (c))') --> \dfrac{a }{\dfrac{b}{c}} print(to_frac'((a)/((b)/(c)))/(e)') --> \dfrac{\dfrac{a}{\dfrac{b}{c}}}{e} print(to_frac'(a)/(b)/(c)/(d)') --> \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}
The 'replace' argument of string.gsub can be a function. Using that function, you can apply the substitution recursively to the numerator and denominator and build the result that way. string.sub can be used to remove the parentheses from the numerator and denominator. function to_frac(expr) return (expr:gsub('%s*(%b())%s*/%s*(%b())%s*', function(num, denom) return '\\dfrac{'..to_frac(num:sub(2,-2))..'}{' ..to_frac(denom:sub(2,-2))..'}' end)) end expr = ' (a )/((b) / (c))' -- \dfrac{a }{\dfrac{b}{c}} print(to_frac(expr)) expr = '((a)/((b)/(c)))/(e)' -->\dfrac{\dfrac{a}{\dfrac{b}{c}}}{e} print(to_frac(expr)) If you want to go beyond using parentheses for delimiting arguments and obey precedence rules, then look into LPeg.
Search for an item in a Lua list
If I have a list of items like this: local items = { "apple", "orange", "pear", "banana" } how do I check if "orange" is in this list? In Python I could do: if "orange" in items: # do something Is there an equivalent in Lua?
You could use something like a set from Programming in Lua: function Set (list) local set = {} for _, l in ipairs(list) do set[l] = true end return set end Then you could put your list in the Set and test for membership: local items = Set { "apple", "orange", "pear", "banana" } if items["orange"] then -- do something end Or you could iterate over the list directly: local items = { "apple", "orange", "pear", "banana" } for _,v in pairs(items) do if v == "orange" then -- do something break end end
Use the following representation instead: local items = { apple=true, orange=true, pear=true, banana=true } if items.apple then ... end
You're seeing firsthand one of the cons of Lua having only one data structure---you have to roll your own. If you stick with Lua you will gradually accumulate a library of functions that manipulate tables in the way you like to do things. My library includes a list-to-set conversion and a higher-order list-searching function: function table.set(t) -- set of list local u = { } for _, v in ipairs(t) do u[v] = true end return u end function table.find(f, l) -- find element v of l satisfying f(v) for _, v in ipairs(l) do if f(v) then return v end end return nil end
Write it however you want, but it's faster to iterate directly over the list, than to generate pairs() or ipairs() #! /usr/bin/env lua local items = { 'apple', 'orange', 'pear', 'banana' } local function locate( table, value ) for i = 1, #table do if table[i] == value then print( value ..' found' ) return true end end print( value ..' not found' ) return false end locate( items, 'orange' ) locate( items, 'car' ) orange found car not found
Lua tables are more closely analogs of Python dictionaries rather than lists. The table you have create is essentially a 1-based indexed array of strings. Use any standard search algorithm to find out if a value is in the array. Another approach would be to store the values as table keys instead as shown in the set implementation of Jon Ericson's post.
This is a swiss-armyknife function you can use: function table.find(t, val, recursive, metatables, keys, returnBool) if (type(t) ~= "table") then return nil end local checked = {} local _findInTable local _checkValue _checkValue = function(v) if (not checked[v]) then if (v == val) then return v end if (recursive and type(v) == "table") then local r = _findInTable(v) if (r ~= nil) then return r end end if (metatables) then local r = _checkValue(getmetatable(v)) if (r ~= nil) then return r end end checked[v] = true end return nil end _findInTable = function(t) for k,v in pairs(t) do local r = _checkValue(t, v) if (r ~= nil) then return r end if (keys) then r = _checkValue(t, k) if (r ~= nil) then return r end end end return nil end local r = _findInTable(t) if (returnBool) then return r ~= nil end return r end You can use it to check if a value exists: local myFruit = "apple" if (table.find({"apple", "pear", "berry"}, myFruit)) then print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1 You can use it to find the key: local fruits = { apple = {color="red"}, pear = {color="green"}, } local myFruit = fruits.apple local fruitName = table.find(fruits, myFruit) print(fruitName) -- "apple" I hope the recursive parameter speaks for itself. The metatables parameter allows you to search metatables as well. The keys parameter makes the function look for keys in the list. Of course that would be useless in Lua (you can just do fruits[key]) but together with recursive and metatables, it becomes handy. The returnBool parameter is a safe-guard for when you have tables that have false as a key in a table (Yes that's possible: fruits = {false="apple"})
function valid(data, array) local valid = {} for i = 1, #array do valid[array[i]] = true end if valid[data] then return false else return true end end Here's the function I use for checking if data is in an array.
Sort of solution using metatable... local function preparetable(t) setmetatable(t,{__newindex=function(self,k,v) rawset(self,v,true) end}) end local workingtable={} preparetable(workingtable) table.insert(workingtable,123) table.insert(workingtable,456) if workingtable[456] then ... end
The following representation can be used: local items = { ["apple"]=true, ["orange"]=true, ["pear"]=true, ["banana"]=true } if items["apple"] then print("apple is a true value.") end if not items["red"] then print("red is a false value.") end Related output: apple is a true value. red is a false value. You can also use the following code to check boolean validity: local items = { ["apple"]=true, ["orange"]=true, ["pear"]=true, ["banana"]=true, ["red"]=false, ["blue"]=false, ["green"]=false } if items["yellow"] == nil then print("yellow is an inappropriate value.") end if items["apple"] then print("apple is a true value.") end if not items["red"] then print("red is a false value.") end The output is: yellow is an inappropriate value. apple is a true value. red is a false value. Check Tables Tutorial for additional information.
function table.find(t,value) if t and type(t)=="table" and value then for _, v in ipairs (t) do if v == value then return true; end end return false; end return false; end
you can use this solution: items = { 'a', 'b' } for k,v in pairs(items) do if v == 'a' then --do something else --do something end end or items = {'a', 'b'} for k,v in pairs(items) do while v do if v == 'a' then return found else break end end end return nothing
A simple function can be used that : returns nil, if the item is not found in table returns index of item, if item is found in table local items = { "apple", "orange", "pear", "banana" } local function search_value (tbl, val) for i = 1, #tbl do if tbl[i] == val then return i end end return nil end print(search_value(items, "pear")) print(search_value(items, "cherry")) output of above code would be 3 nil