Making Lua Like Php

lua-users home
wiki

Here lies a few functions or code snippets that make Lua behave more like PHP.

Note: Some of these PHP-style functions don't do exactly the same as PHP. In some cases this is intentional.

print_r

Based on [PHP print_r]. Based on code by Nick Gammon, hacked by DracoBlue to fit to [PHP print_r]-Style.

Example: print_r{ 5,3,{5,3} } -->

[1] => 5
[2] => 3
[3] => Table 
   {
     [1] => 5
     [2] => 3
   }

Compatibility: Lua 5.0 and 5.1

function print_r (t, indent, done)
  done = done or {}
  indent = indent or ''
  local nextIndent -- Storage for next indentation value
  for key, value in pairs (t) do
    if type (value) == "table" and not done [value] then
      nextIndent = nextIndent or
          (indent .. string.rep(' ',string.len(tostring (key))+2))
          -- Shortcut conditional allocation
      done [value] = true
      print (indent .. "[" .. tostring (key) .. "] => Table {");
      print  (nextIndent .. "{");
      print_r (value, nextIndent .. string.rep(' ',2), done)
      print  (nextIndent .. "}");
    else
      print  (indent .. "[" .. tostring (key) .. "] => " .. tostring (value).."")
    end
  end
end

function print_r (t, indent) -- alt version, abuse to http://richard.warburton.it
  local indent=indent or ''
  for key,value in pairs(t) do
    io.write(indent,'[',tostring(key),']') 
    if type(value)=="table" then io.write(':\n') print_r(value,indent..'\t')
    else io.write(' = ',tostring(value),'\n') end
  end
end

-- alt version2, handles cycles, functions, booleans, etc
--  - abuse to http://richard.warburton.it
-- output almost identical to print(table.show(t)) below.
function print_r (t, name, indent)
  local tableList = {}
  function table_r (t, name, indent, full)
    local serial=string.len(full) == 0 and name
        or type(name)~="number" and '["'..tostring(name)..'"]' or '['..name..']'
    io.write(indent,serial,' = ') 
    if type(t) == "table" then
      if tableList[t] ~= nil then io.write('{}; -- ',tableList[t],' (self reference)\n')
      else
        tableList[t]=full..serial
        if next(t) then -- Table not empty
          io.write('{\n')
          for key,value in pairs(t) do table_r(value,key,indent..'\t',full..serial) end 
          io.write(indent,'};\n')
        else io.write('{};\n') end
      end
    else io.write(type(t)~="number" and type(t)~="boolean" and '"'..tostring(t)..'"'
                  or tostring(t),';\n') end
  end
  table_r(t,name or '__unnamed__',indent or '','')
end

See Also: LuaRecipes - Recursive table print/serialization

a more complete version of print_r

Sorry for the length!

--[[
   Author: Julio Manuel Fernandez-Diaz
   Date:   January 12, 2007
   (For Lua 5.1)
   
   Modified slightly by RiciLake to avoid the unnecessary table traversal in tablecount()

   Formats tables with cycles recursively to any depth.
   The output is returned as a string.
   References to other tables are shown as values.
   Self references are indicated.

   The string returned is "Lua code", which can be procesed
   (in the case in which indent is composed by spaces or "--").
   Userdata and function keys and values are shown as strings,
   which logically are exactly not equivalent to the original code.

   This routine can serve for pretty formating tables with
   proper indentations, apart from printing them:

      print(table.show(t, "t"))   -- a typical use
   
   Heavily based on "Saving tables with cycles", PIL2, p. 113.

   Arguments:
      t is the table.
      name is the name of the table (optional)
      indent is a first indentation (optional).
--]]
function table.show(t, name, indent)
   local cart     -- a container
   local autoref  -- for self references

   --[[ counts the number of elements in a table
   local function tablecount(t)
      local n = 0
      for _, _ in pairs(t) do n = n+1 end
      return n
   end
   ]]
   -- (RiciLake) returns true if the table is empty
   local function isemptytable(t) return next(t) == nil end

   local function basicSerialize (o)
      local so = tostring(o)
      if type(o) == "function" then
         local info = debug.getinfo(o, "S")
         -- info.name is nil because o is not a calling level
         if info.what == "C" then
            return string.format("%q", so .. ", C function")
         else 
            -- the information is defined through lines
            return string.format("%q", so .. ", defined in (" ..
                info.linedefined .. "-" .. info.lastlinedefined ..
                ")" .. info.source)
         end
      elseif type(o) == "number" then
         return so
      else
         return string.format("%q", so)
      end
   end

   local function addtocart (value, name, indent, saved, field)
      indent = indent or ""
      saved = saved or {}
      field = field or name

      cart = cart .. indent .. field

      if type(value) ~= "table" then
         cart = cart .. " = " .. basicSerialize(value) .. ";\n"
      else
         if saved[value] then
            cart = cart .. " = {}; -- " .. saved[value] 
                        .. " (self reference)\n"
            autoref = autoref ..  name .. " = " .. saved[value] .. ";\n"
         else
            saved[value] = name
            --if tablecount(value) == 0 then
            if isemptytable(value) then
               cart = cart .. " = {};\n"
            else
               cart = cart .. " = {\n"
               for k, v in pairs(value) do
                  k = basicSerialize(k)
                  local fname = string.format("%s[%s]", name, k)
                  field = string.format("[%s]", k)
                  -- three spaces between levels
                  addtocart(v, fname, indent .. "   ", saved, field)
               end
               cart = cart .. indent .. "};\n"
            end
         end
      end
   end

   name = name or "__unnamed__"
   if type(t) ~= "table" then
      return name .. " = " .. basicSerialize(t)
   end
   cart, autoref = "", ""
   addtocart(t, name, indent)
   return cart .. autoref
end

A test:

-----------------------------------------------------------
--- testing table.show

t = {1, {2, 3, 4}, default = {"a", "b", d = {12, "w"}, e = 14}}
t.g = t.default

print("-----------------------------------")
print(table.show(t))                -- shows __unnamed__ table

tt = {1, h = {["p-q"] = "a", b = "e", c = {color = 3, name = "abc"}}, 2}

f = table.show
tt[f] = "OK"

print("-----------------------------------")
print(table.show(tt, "tt", "--oo-- ")) -- shows some initial 'indent'

t.m = {}
t.g.a = {}
t.g.a.c = t
t.tt = tt.new
t.show = table.show

print("-----------------------------------")
print(table.show(t, "t"))            -- most typical use

print("-----------------------------------")
print(table.show(math.tan, "tan"))   -- not a table is OK

print("-----------------------------------")
s = "a string"
print(table.show(s, "s"))            -- not a table is OK

The output:

-----------------------------------
__unnamed__ = {
   [1] = 1;
   [2] = {
      [1] = 2;
      [2] = 3;
      [3] = 4;
   };
   ["default"] = {
      [1] = "a";
      [2] = "b";
      ["e"] = 14;
      ["d"] = {
         [1] = 12;
         [2] = "w";
      };
   };
   ["g"] = {}; -- __unnamed__["default"] (self reference)
};
__unnamed__["g"] = __unnamed__["default"];

-----------------------------------
--oo-- tt = {
--oo--    [1] = 1;
--oo--    [2] = 2;
--oo--    ["function: 0x8070e20, defined in (28-99)@newprint_r.lua"] = "OK";
--oo--    ["h"] = {
--oo--       ["b"] = "e";
--oo--       ["c"] = {
--oo--          ["color"] = 3;
--oo--          ["name"] = "abc";
--oo--       };
--oo--       ["p-q"] = "a";
--oo--    };
--oo-- };

-----------------------------------
t = {
   [1] = 1;
   [2] = {
      [1] = 2;
      [2] = 3;
      [3] = 4;
   };
   ["m"] = {};
   ["show"] = "function: 0x8070e20, defined in (28-99)@newprint_r.lua";
   ["g"] = {
      [1] = "a";
      [2] = "b";
      ["e"] = 14;
      ["d"] = {
         [1] = 12;
         [2] = "w";
      };
      ["a"] = {
         ["c"] = {}; -- t (self reference)
      };
   };
   ["default"] = {}; -- t["g"] (self reference)
};
t["g"]["a"]["c"] = t;
t["default"] = t["g"];

-----------------------------------
tan = "function: 0x806f758, C function"
-----------------------------------
s = "a string"

explode

Based on [PHP explode]

Example: explode(" and ","one and two and three and four") --> {"one","two","three","four"}

Compatibility: Lua 5.0 and 5.1 -- By RichardWarburton

function explode(div,str)
  if (div=='') then return false end
  local pos,arr = 0,{}
  -- for each divider found
  for st,sp in function() return string.find(str,div,pos,true) end do
    table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
    pos = sp + 1 -- Jump past current divider
  end
  table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
  return arr
end

implode

Based on [PHP implode]

Use table.concat:

PHP implode(join,array) is equivalent to Lua table.concat(table,join)

PHP: implode(" ",array("this","is","a","test","array")) --> "this is a test array"

Lua: table.concat({"this","is","a","test","array"}," ") --> "this is a test array"

PHP Tables

PHP arrays retain the order that key, value pairs are added. This is not true for Lua by default. But such functionality can be emulated.

function phpTable(...) -- abuse to: http://richard.warburton.it
  local newTable,keys,values={},{},{}
  newTable.pairs=function(self) -- pairs iterator
    local count=0
    return function() 
      count=count+1
      return keys[count],values[keys[count]]
    end
  end
  setmetatable(newTable,{
    __newindex=function(self,key,value)
      if not self[key] then table.insert(keys,key)
      elseif value==nil then -- Handle item delete
        local count=1
        while keys[count]~=key do count = count + 1 end
        table.remove(keys,count)
      end
      values[key]=value -- replace/create
    end,
    __index=function(self,key) return values[key] end
  })
  for x=1,table.getn(arg) do
    for k,v in pairs(arg[x]) do newTable[k]=v end
  end
  return newTable
end

Example Usage:

-- arguments optional
test = phpTable({blue="blue"},{red="r"},{green="g"})

test['life']='bling'
test['alpha']='blong'
test['zeta']='blast'
test['gamma']='blue'
test['yak']='orange'
test['zeta']=nil -- delete zeta

for k,v in test:pairs() do
	print(k,v)
end

The output:

blue    blue
red     r
green   g
life    bling
alpha   blong
gamma   blue
yak     orange

preg_replace

Based on [PHP preg_replace]

Example: preg_replace("\\((.*?)\\)","", " Obvious exits: n(closed) w(open) rift")

The following preg_replace variants support using the wildcards %n in the replace.

1. Using Lua-style regular expressions:

function preg_replace(pat,with,p)
  return (string.gsub(p,pat,with))
end

2. Using PCRE or POSIX regular expressions:

function preg_replace(pat,with,p)
  return (rex.gsub(p,pat,with))
end

See Also


FindPage · RecentChanges · preferences
edit · history
Last edited July 26, 2007 2:12 am GMT (diff)