我看到一个Lua字符串函数列表,我看到.gsub(),用于全局搜索和替换: http://www.gammon.com.au/scripts/doc.php?general=lua_string 所有lua字符串函数: static const luaL_Reg strlib[] = { {"byte", str_byte}, {"char",
所有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, src+init, 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
这个答案是对上述评论的正式重建.