Reputation: 11
I wrote the following code:
rpid = "Remote-Party-ID:<sip:+19>;abc"
local startRPID = string.find(rpid, "<")
local endRPID = string.find(rpid, ">")
local ANI = string.sub(rpid, startRPID, endRPID)
local MRPID = "\"TEST\" "..ANI
local finalRPID = string.gsub(rpid,ANI,MRPID)
print (finalRPID)
Expected result:
Remote-Party-ID:"TEST" <sip:+19>;abc
However, the last replacement (string.gsub(rpid,ANI,MRPID)
) is not happening because of the +
character in ANI
, so the actual result is Remote-Party-ID:<sip:+19>;abc
.
If I pass the string without the +
(rpid = "Remote-Party-ID:<sip:19>;abc"
), the result is as expected (except for the +
, which is of course also missing in the output).
How can I achieve the same with the +
character included?
Upvotes: 1
Views: 156
Reputation: 1013
This uses a balanced pair
local rpid = "Remote-Party-ID:<sip:+19>;abc"
rpid = rpid:gsub("%b<>", '"TEST" %1')
print(rpid)
Result:
Remote-Party-ID:"TEST" <sip:+19>;abc
Upvotes: 4
Reputation: 11171
Your code goes around a couple corners to do a simple thing: You want to find the text enclosed in angle brackets (<
and >
) and prepend something to it.
This can be done using a single call to string.gsub
:
local RPID = "Remote-Party-ID:<sip:+19>;abc"
local finalRPID = rpid:gsub("<.->", function(sip)
return '"TEST" ' .. sip
end)
This varies in some nuances:
1
as a third parameter to gsub
to change this.but it handles your scenario correctly. Alternatively, you could also use match
; after all you don't need more than a single substitution:
local prefix, sip, suffix = RPID:match"(.-)(<.->)(.*)"
local finalRPID = prefix .. '"TEST" ' .. sip .. suffix
You're right, the +
character, serving as a quantifier for "one or more" in patterns, causes the issue since ANI
is interpreted as a pattern. You can fix this by first escaping all magic characters in ANI
using %
signs: ANI:gsub("[][^$()%.*+-?]", "%%%1")
. Similarly, you would need to escape %
signs in MRPID
(which I renamed to newANI
) to avoid them being treated as "capture indices": MRPID:gsub("%%", "%%%%")
. This yields:
local RPID = "Remote-Party-ID:<sip:+19>;abc"
// could just use `string.match` to extract this
local startANI, endANI = RPID:find"<", RPID:find">"
local ANI = RPID:sub(startANI, endANI)
-- Escape ANI to get a pattern for literal replacement.
local patt = ANI:gsub("[]%-%%[^$().*+?]", "%%%1")
local newANI = '"TEST" ' .. ANI
-- Escape to get a literal replacement string. Won't be needed here if there won't ever be `%` signs in `newANI`.
local repl = newANI:gsub("%%", "%%%%")
local finalRPID = RPID:gsub(ANI, newANI)
This code is however needlessly complicated; I merely fixed it to demonstrate how to do a literal string replacement in Lua by escaping the arguments of gsub
. Extracted as a function:
function string:replace(needle, repl)
needle = needle:gsub("[]%-%%[^$().*+?]", "%%%1")
repl = repl:gsub("%%", "%%%%")
return self:gsub(needle, repl)
end
(you might want to make this a local function
to not modify the string
table, which could conflict with other scripts doing the same)
Upvotes: 2