openwrt实践 | Lua快速入门教程

1200px-Lua_logo.svg.png

一、定义变量


  • 数字,双精度
local free_space            = 6
free_space                  = 6.666666
  • 字符串度
local usb_local_path        = "/mnt/sda1/"
local plug_flash_db         = '/usr/share/ipk/plug_db'

--定义多行字符串
local plug_config_path      = [[/tmp/init_plug.config]]
  • 空类型
local plug_location         = nil

注:nil,即NULL,支持垃圾回收

  • 布尔类型
-------------------------------
--fasle:    nil & false
--true:     0 & "" & 非空字符串
-------------------------------
local IS_USB_EXIST          = false
--空表
local plug_log              = {}

--数组
local arr                   = {
    [1]                     = 10,
    [2]                     = 20,
    [3]                     = 30,
    [4]                     = 40,
    [5]                     = 50
}
--键值对
local plug_get_opt_list     = {
    ["get_plug"]            = "get_plug",
    ["get_plug_status"]     = "get_plug_status"
}
local PLUG_STATUS           = {
    ["DOWNLOADING"]         = 1,
    ["INSTALLING"]          = 2,
    ["FAILED"]              = 3,
    ["START"]               = 4,
    ["STOP"]                = 5
}

二、控制语句


  • if-else 语句
if plug_opt == "remove" then
    res = remove_plugin(plug_code, plug_exec_fname)
    
elseif plug_opt == "cmd_ctrl" then
    res = control_plugin(cmd_argc_list, plug_exec_fname)
    
else
    res, code = false, PLUG_OPT_CODE.ERROR
end
  • while 循环
while value >= 36 do
    local temp = value % 36
    ...
end
  • for循环
local flash_db_res, res = {}, {}
flash_db_res = db_util:fetch_plug_status(plug_code)

for k, v in pairs(flash_db_res) do
    table.insert(res, v)
end

for i = 1, #week_repeat, 2 do
    ...
end
  • until循环
repeat
   ...
until sum > 1000

三、函数


  • 函数与其他类型一样,属于基本类型,且也分局部和全局之分
  • 普通函数
function do_remove_by_opkg(plug_name)
    local cmd = "opkg remove "..plug_name 
    plug_mkdir_slink()
    lue(cmd)
    plug_rmdir_slink()
end

  • 多返回值函数
function install_plug(plug_code, plug_md5, plug_url)
    
    ...
    
    --TODO:subthread
    local plug_local_path   = download_plug(plug_code, plug_url)
    local check_md5_flag    = check_plug_md5(plug_md5)
    if check_md5_flag == false then
        clr_failed_plug_from_db(plug_code)
        return false, PLUG_OPT_CODE.CHECK_MD5_ERROR
    end
    
    ...
    
    return true, PLUG_OPT_CODE.NORMAL
end
  • 递归函数
function RecursionPreOrder(BiTree t){
    if(t ~= nil){
        print(t.data);
        RecursionPreOrder(t.lchild);
        RecursionPreOrder(t.rchild);
    }
}
  • 闭包函数
function external_func()
    local i = 0
    
    function internal_func()
        i = i + 1
        return i
    end
    
    return internal_func
end

local closure_func = external_func()
print(closure_func())   --1
print(closure_func())   --2
print(closure_func())   --3
print(closure_func())   --4

四、Table操作


  • 初始化table
local PLUG_OPT_CODE             = {
    ["NORMAL"]                  = 200,
    ...
}
  • 获取table值
print(PLUG_OPT_CODE.NORMAL)
print(PLUG_OPT_CODE["NORMAL"])
  • 遍历table
local is_uniq = true
for usb_k,usb_v in pairs(usb_db_res) do
    for res_k, res_v in pairs(res) do
        if res_v["plug_code"] == usb_v["plug_code"] then
            is_uniq = false
            break 
        end
    end
    if is_uniq == true then
        table.insert(res, usb_v)
    end
end

五、面向对象EXAMPLE


  • db_util类
module("plug_db_util", package.seeall)
db_util       = {}

function db_util:fetch_plug(plug_code)
    ...
end
  • db_util类实例
local db_util = require "plug_db_util".db_util

function get_plug_from_db(plug_param)
    
    ...
    
    if plug_param.plug_code ~= nil and plug_param.plug_opt ~= "get_plug_status" then
        init_plug_install_local_path(STORAGE_NODE["FLASH"])
        plug_location = STORAGE_NODE["FLASH"]
        local res = db_util:fetch_plug(plug_param.plug_code)
        
        if next(res) == nil  and IS_USB_EXIST == true then
            init_plug_install_local_path(STORAGE_NODE["USB"])
            plug_location = STORAGE_NODE["USB"]
            res = db_util:fetch_plug(plug_param.plug_code)
        end
        ...
    end
    ...
    
end

六、常用标准库函数


  • string库
local str = [[rh_Jameson]]

print( string.lower(str) )          --rh_jameson
print( string.upper(str) )          --RH_JAMESON
print( string.len(str) )            --10

--字符串重复输出
print( string.rep(str, 3) )         --rh_Jamesonrh_Jamesonrh_Jameson

--字符串截取
print( string.sub(str, 4, -1) )     --Jameson
print( string.sub(str, 4, 10) )     --Jameson
print( string.sub(str, 4, #str) )   --Jameson


--字符串查找,返回起始  & 结束索引
print( string.find(str, "%_"))  --3 3
print( string.sub(str, string.find(str, "%_") + 1, #str ) ) --Jameson

--字符串匹配,匹配不上返回nil
print( string.match(str, "%_") )    --_

--字符串替换
print( string.gsub(str, '_', '@'))  --rh@Jameson 1

--字符串格式化输出
--openwrt is operate system of router, 6666 ...
print( string.format("%s is %s of router, %d %s", "openwrt", "operate system", 6666, "..."))

  • os库
os.remove("/tmp/"..lock_file)
os.rename("/tmp/"..lock_file.."rename")
os.execute("rm /tmp/init_plug.config")
os.time()
os.date()

  • io库
---------------------
--PLUG OPT LOCK DEMO
----------------------
function plug_opt_lock(lock_file)
    local ct = os.time()
    local file = io.open("/tmp/".. lock_file, "w")
    file:write(ct);
    file:close();
end

function is_plug_lock(lock_file, timeval)
    local file = io.open("/tmp/"..lock_file, "r")
    if file == nil then
        return false
    end
    local ctn = file:read()
    if ctn == nil or ctn == "" then
        ctn = 0
    end
    file:close();
    local ct = os.time()
    if(ct - tonumber(ctn) > timeval) then
        os.remove("/tmp/"..lock_file);
        return false;
    end
    return true;
end
---------------------
--CRON WIFI DEMO
----------------------
function get_smart_wifi_info()
    local res = {}
    local smart_wifi_info = io.open("/etc/crontabs/root", "r")
    if smart_wifi_info == nil then
        return "false"
    end
    for line in smart_wifi_info:lines() do
       ... 
    end
    ...
    smart_wifi_info:close()
    return res;
end
  • table库
for key,val in pairs(key_res) do
    table.insert(format_res, key)
end 
table.sort(format_res)

function randomstring(len)
    local allstr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    local maxlen = string.len(allstr)
    local srt = {}
    for i=1,len,1 do
        local index = random(1, maxlen)
        srt[i] = string.sub(allstr, index, index)
    end
    return table.concat(srt, "")
end

local tb_ex     = {}
local tb_inter  = {
    ["name"]        ="rh_Jameson",
    ["en-name"]     ="rh_Jameson",
    ["zh-name"]     ="rh_Jameson"
}

for k, v in pairs(tb_inter) do
    print(k .. " : " .. v)
end

table.insert(tb_ex, tb_inter)
table.insert(tb_ex, {
                ["mac"]   = 1,
                ["ip"] = 2,
                ["wifi"] = 3,
                ["devicename"] = 4,
                ["orgname"] = 5
            })

for k, v in pairs(tb_ex) do
    --print(k .. " : " .. v)
    print("----------------------")
    print(k)
    print(v)
    for kk, vv in pairs(v) do
       print(kk)
       print(vv) 
    end
    print("----------------------")
end

七、其他函数


  • type(): 返回参数的类型名
if type(plug_code_list) == "string" then
    plug_code_list = cjson.decode(plug_code_list)
end
  • next(): 可用来检测表是否为空
if next(ret) ~= nil then
    table.insert(res, ret)
end
  • pcall(): 类似try {...} catch {...}
function plug_opt(plug_param)
    local format_res, exec_res = {}, {}
    local status = nil
    status, exec_res = pcall(plug_opt_exec, plug_param)
    if status == false then
        log_res(plug_param.plug_opt, exec_res)
        return print_res(format_res, exec_res, PLUG_OPT_CODE.OTHER_ERROR)
    else
        format_res = exec_res
        return format_res
    end
end
  • math.random()
function random(m, n)
    local socket = require("socket")
    local t = string.format("%f", socket.gettime())
    local st = string.sub(t, string.find(t, "%.") + 1, -1)
    math.randomseed(tonumber(string.reverse(st)))
    return math.random(m,n)
end

八、设计模式: lua将多个if-else优化成键值对形式


原有形式:


function do_plug_set_opt(res, plug_opt, plug_code, plug, plug_param)
    local format_res = res
    local code = nil

    if plug_code and plug_opt == "install" then
        local install_node  = check_plug_code_flag(plug_code)
        local plug_install_location, specify_res   = specify_install_storage_node(install_node, res)
        if specify_res["code"] then
            require "MZLog".log(3, res)
            log_res(plug_param.plug_opt, res)
            return specify_res
        end
        res, code = install_plugin(plug_code, plug_param.plug_md5, plug_param.plug_url, plug_install_location)

    elseif plug_code and plug["plug_name"] then
        local plug_exec_fname = get_plug_exec_file_name(plug["plug_code"])
        init_plug_install_local_path(plug_location)
        if plug_opt == "remove" then
            res = remove_plugin(plug_code, plug_exec_fname)

        elseif plug_opt == "start"then
            res = start_plugin(plug_code, plug_exec_fname)

        elseif plug_opt == "stop" then
            res = stop_plugin(plug_code, plug_exec_fname)

        elseif plug_opt == "cmd_ctrl" then
            res = control_plugin(plug_param.cmd_argc_list, plug_exec_fname)

        elseif plug_opt == "upgrade" then
            res, code = upgrade_plugin(plug_code, plug_param.plug_md5, plug_param.plug_url)
        end
    end
    if code == nil then
        format_res = print_res(format_res, res, PLUG_OPT_CODE.NORMAL)
    else
        format_res = print_res(format_res, res, code)
    end
    return format_res
end

优化形式:


plug_set_opt_action               = {
    ["install"]             = plug_opt_util.install_plugin,
    ["async_install"]       = plug_opt_util.async_install_plugin,
    ["remove"]              = plug_opt_util.remove_plugin,
    ["async_remove"]        = plug_opt_util.async_remove_plugin,
    ["start"]               = plug_opt_util.start_plugin,
    ["stop"]                = plug_opt_util.stop_plugin,
    ["cmd_ctrl"]            = plug_opt_util.control_plugin,
    ["upgrade"]             = plug_opt_util.upgrade_plugin,
    ["async_upgrade"]       = plug_opt_util.async_upgrade_plugin
}
--------------------------------plug_opt_util-----------------------------------

function do_plug_set_opt(res, plug_opt, plug_code, plug, plug_param)
    local format_res, code = res, nil
    if plug["plug_name"] then
        plug_param.plug_exec_fname = plug_info_util.get_plug_exec_file_name(plug["plug_code"])
        local plug_location = plug_info_util.get_plug_location()
        init_plug_install_local_path(plug_location)
    end
    code, res = plug_set_opt_action[plug_opt](plug_param)
    format_res = print_res(format_res, res, code)
    return format_res
end

推荐阅读更多精彩内容

  • Address:https://www.zybuluo.com/XiangZhou/note/208532 Exp...
    天蠍蒗漫阅读 10,550评论 2 55
  • github地址,欢迎大家提交更新。 express() express()用来创建一个Express的程序。ex...
    Programmer客栈阅读 2,045评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 131,272评论 18 138
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 5,411评论 0 17
  • https://www.zhihu.com/question/20946174
    夏天氧气阅读 121评论 0 0
  • 爱情果然能点亮你的整个生活,为他欢喜为他忧,患得患失,整个全是因为一个人啊。他的表情他的话,都在牵动你的情绪。想每...
    裳璎珞阅读 112评论 0 1
  • 狂放让压抑的环境得到炸裂释放,给我百吨硫磺与硝,再给我一个炼丹的术士,去炸毁一座了无人烟的荒山,坟里的孤鬼会惊醒,...
    新人素阅读 124评论 0 0