Lua 字符串插值

Lua 字符串插值

Lua 的格式化字符串又臭又長(zhǎng)机久,不僅需要輸入格式化模式,還存在參數(shù)冗余赔嚎,比如:

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 中,格式化字符串可以使用多種形式尤误,其中一種是字符串插值侠畔,就解決了這個(gè)問(wèn)題,如下:

name = "DoooReyn"
 "I am {name}".format(name=name)
# output
# I am DoooReyn损晤,我來(lái)自中國(guó)

于是就想 Lua 可不可以這么搞软棺。那么就來(lái)嘗試一下吧:

  • 首先,定義下提取變量的規(guī)范:{var}尤勋,模式匹配為:{%w+}
  • 接下來(lái)喘落,準(zhǔn)備解析格式化字符串,可以使用 Lua 的 string.gsub
  • 最后最冰,提取到變量名之后瘦棋,進(jìn)行替換操作即可

于是得到:

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

測(cè)試一下:

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

完美!

后記

本來(lái)還想到另外一種做法锌奴,使用 debug.getlocal 獲取調(diào)用 string.interpolate 之前的局部變量映射表來(lái)代替 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]
            -- 轉(zhuǎn)化為字符串
            val = tostring(val == nil and '' or val)
            return val
        end
    )
    return ret
end

這樣一來(lái)兽狭,就可以省略 keys,使用起來(lái)也更靈活:

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

但是這樣存在一些問(wèn)題:

  • 一是,如果局部變量很多箕慧,緩存的局部變量表就會(huì)很大服球,很浪費(fèi)內(nèi)存;如果改為每提取一個(gè)變量就去查詢一次颠焦,額外的操作又會(huì)很多斩熊;
  • 二是,如果變量是全局的伐庭,getlocal 是找不到的粉渠,于是就要增加去全局中查找的操作。

目前沒(méi)有想到很好的解決方法圾另,還是推薦使用第一種方式霸株,畢竟它目的足夠清楚,也不會(huì)有額外的損耗集乔。


?? 如果你喜歡這篇文章去件,請(qǐng)給我一個(gè)Star?吧!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扰路,隨后出現(xiàn)的幾起案子尤溜,更是在濱河造成了極大的恐慌,老刑警劉巖汗唱,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宫莱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡哩罪,警方通過(guò)查閱死者的電腦和手機(jī)授霸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)际插,“玉大人绝葡,你說(shuō)我怎么就攤上這事「桂模” “怎么了藏畅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)功咒。 經(jīng)常有香客問(wèn)我愉阎,道長(zhǎng),這世上最難降的妖魔是什么力奋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任榜旦,我火速辦了婚禮,結(jié)果婚禮上景殷,老公的妹妹穿的比我還像新娘溅呢。我一直安慰自己澡屡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布咐旧。 她就那樣靜靜地躺著驶鹉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铣墨。 梳的紋絲不亂的頭發(fā)上室埋,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音伊约,去河邊找鬼姚淆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屡律,可吹牛的內(nèi)容都是我干的腌逢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼超埋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼上忍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纳本,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腋颠,沒(méi)想到半個(gè)月后繁成,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡淑玫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年巾腕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片絮蒿。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尊搬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出土涝,到底是詐尸還是另有隱情佛寿,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布但壮,位于F島的核電站冀泻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜡饵。R本人自食惡果不足惜弹渔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溯祸。 院中可真熱鬧肢专,春花似錦舞肆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至欧募,卻和暖如春压状,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跟继。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工种冬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舔糖。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓娱两,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親金吗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子十兢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 字符串插值,就是將變量摇庙、常量以及表達(dá)式插入到字符串中的一種技術(shù)旱物,它可以避免字符串拼接的問(wèn)題,很多語(yǔ)言都支持了此功能...
    西賓聯(lián)盟_墨淵閱讀 821評(píng)論 0 1
  • 基礎(chǔ)知識(shí) Lua中的string和c#中相同卫袒,string類型的值一旦改變宵呛,便要為新值開(kāi)辟空間,并指向此空間夕凝。也就...
    Charon_ted閱讀 1,054評(píng)論 0 1
  • 作者:Ole Begemann宝穗,原文鏈接,原文日期:2016-12-07譯者:Cwift码秉;校對(duì):walkingwa...
    梁杰_numbbbbb閱讀 640評(píng)論 0 0
  • 開(kāi)發(fā)程序過(guò)程中转砖,去處理格式化的內(nèi)容輸出是很常見(jiàn)的须鼎,無(wú)論你開(kāi)發(fā)控制臺(tái)程序,Web應(yīng)用還是移動(dòng)開(kāi)發(fā)都有類似的場(chǎng)景府蔗。C#...
    Dino閱讀 982評(píng)論 0 49
  • 基礎(chǔ) 我們已經(jīng)習(xí)慣了像這樣的字符串插值 與以前相比莉兰,語(yǔ)法已經(jīng)極大的改進(jìn),以前是這樣的 性能也改進(jìn)了礁竞,以前可能是這樣...
    星星星宇閱讀 1,084評(píng)論 2 3