我如何循环遍历字符串中的每个 string.gmatch 然后用字节码版本替换匹配项?
How'd i loop through every string.gmatch in a string then replacing the matches with a bytecoded version of that?
如何在不更改不匹配项的情况下更改字符串中匹配的所有内容?
local a = "\" Hello World! I want to replace this with a bytecoded version of this!\" but not this!"
for i in string.gmatch(a, "\".*\"") do
print(i)
end
例如我想要[["Hello World!" Don't Replace this!]]
到[["18811480" Don't Replace this!]]
你需要string.gsub
.
local a = "\"Hello World!\" Don't Replace this!"
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
a = string.gsub(a, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
print(a)
你的问题有点棘手,因为它可能涉及:
- Lua patterns
string.gsub
function
- 使用
string.byte
访问字符串的字节
- 字符串连接
table.concat
首先,如果您需要实现 Lua
模式,请知道有一个非常方便的 Lua
语法,它非常适合处理 引用的字符串。使用此语法,您可以使用字符 [[
和 ]]
代替 opening/closing 带双引号的字符串。关键区别在于,在这些标记之间,您不必再转义引用的字符串!
String = [["Hello World!" Don't Replace this!]]
然后,我们需要构建正确的 Lua
模式,可能是匹配双引号 ("
) 然后匹配所有 的字符不是 双引号 ("
),这给了我们以下模式:
[["([^"]+)"]]
| **** |
| \-> the expression to match
| |
quote quote
那么如果我们研究函数string.gsub
,我们可以知道该函数可以在匹配模式时调用callback
,匹配的字符串将替换为 return 回调值.
function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
在这个function
中,我们遍历匹配字符串的所有字符。然后对于每个字符,我们使用函数 string.byte
提取其字节值,并使用 string.format
函数将其转换为字符串。我们将这个字符串放在一个临时数组中,我们将在函数末尾连接该数组。
将子字符串连接成更大字符串的函数是table.concat
。这是一个非常方便的功能,可以按如下方式使用:
> table.concat({ [[]], [[]], [[]] })
我们剩下要做的就是测试这个出色的功能:
> String = [["Hello World!" Don't Replace this!]]
> NewString = String:gsub([["([^"]+)"]], ConvertToByteString)
> NewString
\"18811480\" Don't Replace this!
编辑:我收到了一些关于代码性能的评论,我个人不太关注性能,我专注于让代码正确和简单。为了解决性能问题,我写了一个微基准来比较版本:
function SOLUTION_DarkWiiPlayer (String)
local result = String:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end)
return result
end
function SOLUTION_Robert (String)
local function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
local Result = String:gsub([["([^"]+)"]], ConvertToByteString)
return Result
end
function SOLUTION_Piglet (String)
return String:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)
end
function SOLUTION_Renshaw (String)
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
local Result = string.gsub(String, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
return Result
end
String = "\"Hello World!\" Don't Replace this!"
print("INITIAL REQUIREMENT FROM OP ", [[\"18811480\" Don't Replace this!]])
print("TEST SOLUTION_Robert: ", SOLUTION_Robert(String))
print("TEST SOLUTION_DarkWiiPlayer:", SOLUTION_DarkWiiPlayer(String))
print("TEST SOLUTION_Piglet: ", SOLUTION_Piglet(String))
print("TEST SOLUTION_Renshaw: ", SOLUTION_Renshaw(String))
结果表明,只有一个答案可以 100% 满足 OP 的要求。其他答案没有正确处理第一个和结束双引号 "
。
INITIAL REQUIREMENT FROM OP \"18811480\" Don't Replace this!
TEST SOLUTION_Robert: \"18811480\" Don't Replace this!
TEST SOLUTION_DarkWiiPlayer: "18811480" Don't Replace this!
TEST SOLUTION_Piglet: 18811480 Don't Replace this! 1
TEST SOLUTION_Renshaw: "18811480" Don't Replace this!
要完成此 post,可以更深入地研究并使用微基准检查代码性能,该基准可能 copy/paste 直接在 Lua
解释器中。
function SOLUTION_DarkWiiPlayer (String)
local result = String:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end)
return result
end
function SOLUTION_Robert (String)
local function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
local Result = String:gsub([["([^"]+)"]], ConvertToByteString)
return Result
end
function SOLUTION_Piglet (String)
return String:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)
end
function SOLUTION_Renshaw (String)
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
local Result = string.gsub(String, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
return Result
end
---
--- Micro-benchmark environment
---
COUNT = 600000
function TEST_Function (Name, Function, String, Count)
local TimerStart = os.clock()
for Index = 1, Count do
Function(String)
end
local ElapsedSeconds = (os.clock() - TimerStart)
print(string.format("[%25.25s] %f sec", Name, ElapsedSeconds))
end
String = "\"Hello World!\" Don't Replace this!"
TEST_Function("SOLUTION_DarkWiiPlayer", SOLUTION_DarkWiiPlayer, String, COUNT)
TEST_Function("SOLUTION_Robert", SOLUTION_Robert, String, COUNT)
TEST_Function("SOLUTION_Piglet", SOLUTION_Piglet, String, COUNT)
TEST_Function("SOLUTION_Renshaw", SOLUTION_Renshaw, String, COUNT)
结果显示@DarkWiiPlayer的回答是最快的
[ SOLUTION_DarkWiiPlayer] 6.363000 sec
[ SOLUTION_Robert] 9.605000 sec
[ SOLUTION_Piglet] 7.943000 sec
[ SOLUTION_Renshaw] 8.875000 sec
local a = "\"Hello World!\" but not this!"
print(a:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end))
local a = "\" Hello World! I want to replace this with a bytecoded version of this!\" but not this!"
print((a:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)))
如何在不更改不匹配项的情况下更改字符串中匹配的所有内容?
local a = "\" Hello World! I want to replace this with a bytecoded version of this!\" but not this!"
for i in string.gmatch(a, "\".*\"") do
print(i)
end
例如我想要[["Hello World!" Don't Replace this!]]
到[["18811480" Don't Replace this!]]
你需要string.gsub
.
local a = "\"Hello World!\" Don't Replace this!"
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
a = string.gsub(a, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
print(a)
你的问题有点棘手,因为它可能涉及:
- Lua patterns
string.gsub
function- 使用
string.byte
访问字符串的字节
- 字符串连接
table.concat
首先,如果您需要实现 Lua
模式,请知道有一个非常方便的 Lua
语法,它非常适合处理 引用的字符串。使用此语法,您可以使用字符 [[
和 ]]
代替 opening/closing 带双引号的字符串。关键区别在于,在这些标记之间,您不必再转义引用的字符串!
String = [["Hello World!" Don't Replace this!]]
然后,我们需要构建正确的 Lua
模式,可能是匹配双引号 ("
) 然后匹配所有 的字符不是 双引号 ("
),这给了我们以下模式:
[["([^"]+)"]]
| **** |
| \-> the expression to match
| |
quote quote
那么如果我们研究函数string.gsub
,我们可以知道该函数可以在匹配模式时调用callback
,匹配的字符串将替换为 return 回调值.
function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
在这个function
中,我们遍历匹配字符串的所有字符。然后对于每个字符,我们使用函数 string.byte
提取其字节值,并使用 string.format
函数将其转换为字符串。我们将这个字符串放在一个临时数组中,我们将在函数末尾连接该数组。
将子字符串连接成更大字符串的函数是table.concat
。这是一个非常方便的功能,可以按如下方式使用:
> table.concat({ [[]], [[]], [[]] })
我们剩下要做的就是测试这个出色的功能:
> String = [["Hello World!" Don't Replace this!]]
> NewString = String:gsub([["([^"]+)"]], ConvertToByteString)
> NewString
\"18811480\" Don't Replace this!
编辑:我收到了一些关于代码性能的评论,我个人不太关注性能,我专注于让代码正确和简单。为了解决性能问题,我写了一个微基准来比较版本:
function SOLUTION_DarkWiiPlayer (String)
local result = String:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end)
return result
end
function SOLUTION_Robert (String)
local function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
local Result = String:gsub([["([^"]+)"]], ConvertToByteString)
return Result
end
function SOLUTION_Piglet (String)
return String:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)
end
function SOLUTION_Renshaw (String)
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
local Result = string.gsub(String, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
return Result
end
String = "\"Hello World!\" Don't Replace this!"
print("INITIAL REQUIREMENT FROM OP ", [[\"18811480\" Don't Replace this!]])
print("TEST SOLUTION_Robert: ", SOLUTION_Robert(String))
print("TEST SOLUTION_DarkWiiPlayer:", SOLUTION_DarkWiiPlayer(String))
print("TEST SOLUTION_Piglet: ", SOLUTION_Piglet(String))
print("TEST SOLUTION_Renshaw: ", SOLUTION_Renshaw(String))
结果表明,只有一个答案可以 100% 满足 OP 的要求。其他答案没有正确处理第一个和结束双引号 "
。
INITIAL REQUIREMENT FROM OP \"18811480\" Don't Replace this!
TEST SOLUTION_Robert: \"18811480\" Don't Replace this!
TEST SOLUTION_DarkWiiPlayer: "18811480" Don't Replace this!
TEST SOLUTION_Piglet: 18811480 Don't Replace this! 1
TEST SOLUTION_Renshaw: "18811480" Don't Replace this!
要完成此 post,可以更深入地研究并使用微基准检查代码性能,该基准可能 copy/paste 直接在 Lua
解释器中。
function SOLUTION_DarkWiiPlayer (String)
local result = String:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end)
return result
end
function SOLUTION_Robert (String)
local function ConvertToByteString (MatchedString)
local ByteStrings = {}
local Len = #MatchedString
ByteStrings[#ByteStrings+1] = [[\"]]
for Index = 1, Len do
local Byte = MatchedString:byte(Index)
ByteStrings[#ByteStrings+1] = string.format([[\%d]], Byte)
end
ByteStrings[#ByteStrings+1] = [[\"]]
return table.concat(ByteStrings)
end
local Result = String:gsub([["([^"]+)"]], ConvertToByteString)
return Result
end
function SOLUTION_Piglet (String)
return String:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)
end
function SOLUTION_Renshaw (String)
local function convert(str)
local byte_str = ""
for i = 1, #str do
byte_str = byte_str .. "\" .. tostring(string.byte(str, i))
end
return byte_str
end
local Result = string.gsub(String, "\"(.*)\"", function(matched_str)
return "\"" .. convert(matched_str) .. "\""
end)
return Result
end
---
--- Micro-benchmark environment
---
COUNT = 600000
function TEST_Function (Name, Function, String, Count)
local TimerStart = os.clock()
for Index = 1, Count do
Function(String)
end
local ElapsedSeconds = (os.clock() - TimerStart)
print(string.format("[%25.25s] %f sec", Name, ElapsedSeconds))
end
String = "\"Hello World!\" Don't Replace this!"
TEST_Function("SOLUTION_DarkWiiPlayer", SOLUTION_DarkWiiPlayer, String, COUNT)
TEST_Function("SOLUTION_Robert", SOLUTION_Robert, String, COUNT)
TEST_Function("SOLUTION_Piglet", SOLUTION_Piglet, String, COUNT)
TEST_Function("SOLUTION_Renshaw", SOLUTION_Renshaw, String, COUNT)
结果显示@DarkWiiPlayer的回答是最快的
[ SOLUTION_DarkWiiPlayer] 6.363000 sec
[ SOLUTION_Robert] 9.605000 sec
[ SOLUTION_Piglet] 7.943000 sec
[ SOLUTION_Renshaw] 8.875000 sec
local a = "\"Hello World!\" but not this!"
print(a:gsub('"[^"]*"', function(str)
return str:gsub('[^"]', function(char)
return "\" .. char:byte()
end)
end))
local a = "\" Hello World! I want to replace this with a bytecoded version of this!\" but not this!"
print((a:gsub('%b""' , function (match)
local ret = ""
for _,v in ipairs{match:byte(1, -1)} do
ret = ret .. string.format("\%d", v)
end
return ret
end)))