美文网首页Lua
Lua 字符串插值

Lua 字符串插值

作者: 码上说 | 来源:发表于2022-03-07 17:40 被阅读0次

Lua 字符串插值

Lua 的格式化字符串又臭又长,不仅需要输入格式化模式,还存在参数冗余,比如:

print(string.format('Hi! %s am %s, %s am from %s', 'I', 'DoooReyn', 'I', 'China'))
-- output: Hi! I am DoooReyn, I am from China

于是就想到,在 Python 中,格式化字符串可以使用多种形式,其中一种是字符串插值,就解决了这个问题,如下:

name = "DoooReyn"
 "I am {name}".format(name=name)
# output
# I am DoooReyn,我来自中国

于是就想 Lua 可不可以这么搞。那么就来尝试一下吧:

  • 首先,定义下提取变量的规范:{var},模式匹配为:{%w+}
  • 接下来,准备解析格式化字符串,可以使用 Lua 的 string.gsub
  • 最后,提取到变量名之后,进行替换操作即可

于是得到:

function string.interpolate(fmt, keys)
    local ret =
        string.gsub(
        fmt,
        '{%w+}',
        function(c)
            local key = string.match(c, "(%w+)")
            -- 添加数字索引支持
            key = tonumber(key) or key
            local val = keys[key]
            -- 转化为字符串
            val = tostring(val == nil and '' or val)
            return val
        end
    )
    return ret
end

测试一下:

print(string.interpolate('Hi! {who} am {name}, {who} am from {from}', {who = 'I', name = 'DoooReyn', from = 'China'}))
-- output: Hi! I am DoooReyn, I am from China
print(string.interpolate('Hi! {1} am {2}, {1} am from {3}', {'I', 'DoooReyn', 'China'}))
-- output: Hi! I am DoooReyn, I am from China

完美!

后记

本来还想到另外一种做法,使用 debug.getlocal 获取调用 string.interpolate 之前的局部变量映射表来代替 keys:

local function getLocals(level)
    local i = 1
    local locals = {}
    while true do
        local name, value = debug.getlocal(level, i)
        if not name then
            break
        end
        locals[name] = value
        i = i + 1
        print('locals: ', name, value)
    end
    return locals
end

function string.interpolate(fmt)
    local locals = getLocals(3)
    local ret =
        string.gsub(
        fmt,
        '{%w+}',
        function(c)
            local key = string.match(c, "(%w+)")
            local val = locals[key] or _G[key]
            -- 转化为字符串
            val = tostring(val == nil and '' or val)
            return val
        end
    )
    return ret
end

这样一来,就可以省略 keys,使用起来也更灵活:

-- test
local who = "I"
local name = "DoooReyn"
local from = "China"
print(string.interpolate('Hi! {who} am {name}, {who} am from {from}'))

但是这样存在一些问题:

  • 一是,如果局部变量很多,缓存的局部变量表就会很大,很浪费内存;如果改为每提取一个变量就去查询一次,额外的操作又会很多;
  • 二是,如果变量是全局的,getlocal 是找不到的,于是就要增加去全局中查找的操作。

目前没有想到很好的解决方法,还是推荐使用第一种方式,毕竟它目的足够清楚,也不会有额外的损耗。


🤠 如果你喜欢这篇文章,请给我一个Star⭐吧!

相关文章

  • Lua 字符串插值

    Lua 字符串插值 Lua 的格式化字符串又臭又长,不仅需要输入格式化模式,还存在参数冗余,比如: 于是就想到,在...

  • AngularJS学习之路——表达式(2)

    插值字符串 插值字符串就是拥有插值标记的字符串 举个栗子 这里的 {{ expr }} 就是插值标记,str 就是...

  • Lua 语法入门

    赋值 lua 赋值支持多个值同时赋值 table lua table 的 key 可以是数字也可以是字符串,并且 ...

  • Sass插值

    #{} 插值将值插入到字符串是非常有用的,在属性值变量中单独使用插值是明显多余的,您可以这样书写color: #{...

  • 【Lua】(1)基础语法

    一、变量 Lua有8个基本类型:无效值nil、布尔值boolean、数number、字符串string、函数fun...

  • Swift散记1 字符串和字符

    插值字符串中写在括号中的表达式不能包含非转义反斜杠(),并且不能包含回车,不过,插值字符串可以包含其他字面量 Sw...

  • iOS开发之Swift篇(3)—— 字符串String

    目录 版本 创建 可变字符串 字符Character 拼接 索引/插入/删除 截取 (子字符串) 插值 字符串比较...

  • Dart 速查表 codelab

    字符串插值 为了将表达式的值放在字符串中,请使用${expression} 如果表达式为单个值就可以省略{}列: ...

  • 03-Nextflow脚本

    语言基础 Hello world、变量、列表、映射、多重赋值、条件执行、字符串、字符串插值、多行字符串 内置变量 ...

  • Swift学习(五)--String

    一、初始化 多行字符串,使用"""来使用 二、字符串拼接 三种方法 三、字符串插值

网友评论

    本文标题:Lua 字符串插值

    本文链接:https://www.haomeiwen.com/subject/eyunrrtx.html