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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容