Last active
April 28, 2022 10:14
-
-
Save Buy-One/e83d00a782c2429474c178a0b52aec25 to your computer and use it in GitHub Desktop.
Replace Nth capture in a string (versatile)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function replace_Nth_capture(src_str, patt, repl_str, N) -- patt is either a literal string or a pattern; N is ordinal number of the capture to be replaced, if not N or 0 then N is 1 | |
local N = N and tonumber(N) and math.abs(math.floor(N)) | |
if not N or N == 0 then N = 1 end | |
local i = 1 | |
local st, fin, capt | |
local capt_cnt = 0 | |
while i < #src_str do | |
-- OR | |
--repeat | |
st, fin, capt = src_str:find('('..patt..')', i) | |
if capt then capt_cnt = capt_cnt + 1 end | |
if capt_cnt == N then break end | |
i = fin + 1 | |
--OR | |
--until i > #src_str -- > because of fin + 1, doesn't happen with 'while' operator | |
end | |
return N > capt_cnt and src_str or src_str:sub(1, fin-#capt)..repl_str..src_str:sub(fin+1) -- if N is greater than the number of captrures the original string is returned otherwis the one with substitutiones | |
end | |
-- USE CASES | |
local src_str = 'test one test one one test' | |
local repl_str = 'ffsds' | |
--1) | |
for _, v in ipairs({1,6}) do -- replaces 1st and 6th captures of any word | |
src_str = replace_Nth_capture(src_str, '%a+', repl_str, v) | |
end | |
-- result: 'ffsds one test one one ffsds' | |
--2) | |
for _, v in ipairs({{1,2}}) do -- replaces 1st and 3d instances of the word 'test' // every next instance number must be 1 less (2 instead of 3) because their number is being reduced as replacement continues, e.g. to replace 1st and 2nd instances {1,1} must be used | |
src_str = replace_Nth_capture(src_str, 'test', repl_str, v) | |
end | |
-- result: 'ffsds one test one one ffsds' | |
--3) | |
for patt, repl_str in pairs({test = 'test1', one = 'one1'}) do -- replaces 3d instance of 'test' with 'test1' and 3d instance of 'one' with 'one1' | |
src_str = replace_Nth_capture(src_str, patt, repl_str, 3) | |
end | |
-- result: 'test one test one one1 test1' | |
--4) | |
for patt, v in pairs({test = {[2] = 'test1'}, one = {[3] = 'one1'}}) do -- replaces 2d instance of 'test' with 'test1' and 3d instance of 'one' with 'one1' | |
for N, repl_str in pairs(v) do | |
src_str = replace_Nth_capture(src_str, patt, repl_str, N) | |
end | |
end | |
-- result: 'test one test1 one one1 test' | |
--5) | |
for _, t in ipairs({ {one1 = 1}, {one2 = 1} }) do -- raplaces 1st instance of 'test' with 'one1' and 2nd instance of 'test' with 'one2'; for N values see use case 2) above | |
for repl_str, N in pairs(t) do | |
src_str = replace_Nth_capture(src_str, 'test', repl_str, N) | |
end | |
end | |
-- result: 'one1 one one2 one one test' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment