加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

是否有一个Lua字符串replace()函数比gsub()更快的替换?

发布时间:2020-12-14 21:44:36 所属栏目:大数据 来源:网络整理
导读:我看到一个Lua字符串函数列表,我看到.gsub(),用于全局搜索和替换: http://www.gammon.com.au/scripts/doc.php?general=lua_string 所有lua字符串函数: static const luaL_Reg strlib[] = { {"byte",str_byte},{"char",str_char},{"dump",str_dump},{"find"
我看到一个Lua字符串函数列表,我看到.gsub(),用于全局搜索和替换: http://www.gammon.com.au/scripts/doc.php?general=lua_string

所有lua字符串函数:

static const luaL_Reg strlib[] = {
  {"byte",str_byte},{"char",str_char},{"dump",str_dump},{"find",str_find},{"format",str_format},{"gfind",gfind_nodef},{"gmatch",gmatch},{"gsub",str_gsub},{"len",str_len},{"lower",str_lower},{"match",str_match},{"rep",str_rep},{"reverse",str_reverse},{"sub",str_sub},{"upper",str_upper},{NULL,NULL}
};

为什么没有简单,快速,小型(非正则表达式)字符串替换功能?
.gsub()是如此高效以至于没有任何好处吗?

我发现它写于2006年,但它似乎不包括在内:http://lua-users.org/wiki/StringReplace

解决方法

这可能是因为 gsub能够完全执行替换功能所做的事情,而Lua的 design goals包括一个通常不复杂的小型标准库.这样的冗余不需要直接融入语言.

作为一个外部示例,Ruby编程语言在其标准库中提供String#gsub和String#replace.由于这样的决定,Ruby是一种更大,更大的语言.

然而,Lua引以为豪的是一种非常容易扩展的语言.您显示的链接显示了在将Lua整体编译时如何将函数烘焙到标准库中.您也可以将它拼凑在一起以创建模块.

快速修补我们需要的部分(注意我们需要lstrlib.c的lmemfind函数):

#include <lua.h>
#include <lauxlib.h>
#include <string.h>

static const char *lmemfind
(const char *s1,size_t l1,const char *s2,size_t l2) {
    if (l2 == 0)
        return s1;  /* empty strings are everywhere */
    else if (l2 > l1)
        return NULL;  /* avoids a negative 'l1' */

    const char *init;  /* to search for a '*s2' inside 's1' */
    l2--;  /* 1st char will be checked by 'memchr' */
    l1 = l1-l2;  /* 's2' cannot be found after that */

    while (l1 > 0 && (init = (const char *) memchr(s1,*s2,l1)) != NULL) {
        init++;   /* 1st char is already checked */

        if (memcmp(init,s2+1,l2) == 0)
            return init-1;
        else {  /* correct 'l1' and 's1' to try again */
            l1 -= init-s1;
            s1 = init;
        }
    }

    return NULL;  /* not found */
}

static int str_replace(lua_State *L) {
    size_t l1,l2,l3;
    const char *src = luaL_checklstring(L,1,&l1);
    const char *p = luaL_checklstring(L,2,&l2);
    const char *p2 = luaL_checklstring(L,3,&l3);
    const char *s2;
    int n = 0;
    int init = 0;

    luaL_Buffer b;
    luaL_buffinit(L,&b);

    while (1) {
        s2 = lmemfind(src+init,l1-init,p,l2);
        if (s2) {
            luaL_addlstring(&b,src+init,s2-(src+init));
            luaL_addlstring(&b,p2,l3);
            init = init + (s2-(src+init)) + l2;
            n++;
        } else {
            luaL_addlstring(&b,l1-init);
            break;
        }
    }

    luaL_pushresult(&b);
    lua_pushnumber(L,(lua_Number) n);  /* number of substitutions */
    return 2;
}

int luaopen_strrep (lua_State *L) {
    lua_pushcfunction(L,str_replace);
    return 1;
}

我们可以将它编译成具有正确链接的共享对象(cc -shared,cc -bundle等…),并像任何其他带有require的模块一样将其加载到Lua中.

local replace = require 'strrep'

print(replace('hello world','hello','yellow')) -- yellow world,1.0

这个答案是对上述评论的正式重建.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读