这是我第一次发布到这个网站,所以请耐心等待.
考虑以下,有点代表性的字符串:
fld u.a. ldfjal \verb*u.a.* dlf \lstinline$u.a.$ u.a. dfla \url{u.a.}rrr
Run Code Online (Sandbox Code Playgroud)
对于某些背景:\verb*....*并且\lstline$...$是LaTeX宏,其参数不是通过匹配花括号来分隔的,而是通过一个共同的字符分隔:*在的情况下\verb,以及$在的情况下\lstinline.重要的一点是,分隔符可以是除了 {和之外的任何可打印的ASCII字符}; 人们不应该假设*或$将在所有(甚至任何)案件中用作分隔符.另外,\url{...}是一个LaTeX宏,其参数由花括号分隔.应该假定完整的字符串包含utf8编码的字符; 为简单起见,我们假设它们是纯ASCII字符.
我希望建立一个(希望合理有效...)基于Lua的路到全字符串分割成两套子的:(a)在由乳胶宏及其相关参数和各部分(二)其他部分.最终的目标是将"其他部分"提供给string.gsub函数调用.
转到前面的示例,如何将字符串分开
fld u.a. ldfjal \verb*u.a.* dlf \lstinline$u.a.$ u.a. dfla \url{u.a.}rrr
Run Code Online (Sandbox Code Playgroud)
进入"Y"(在类似逐字宏的内部)和"N"(不在类似逐字宏的内部)组件,即
NNNNNNNNNNNNNNNNYYYYYYYYYYYNNNNNYYYYYYYYYYYYYYYYNNNNNNNNNNNYYYYYYYYYYNNN
Run Code Online (Sandbox Code Playgroud)
哦,每个完整的字符串都保证有"N"个组件,但可能没有"Y"组件.原则上,字符串可以以"N"或"Y"分量开始和结束.
我一直试图想出一个使用Lua的字符串库函数的解决方案,但还没有达到目的.:-(
我们假设:
@@\代码:
-- specify number of parameters for every macro,
-- use negative numbers for macros supporting matching pair of curly braces {}
local all_macros = {
verb = 1,
url = -1,
lstinline = -1,
["@Some@Macros"] = -2,
makeatletter = 0
}
-- list all the delimiters (only punctuation and digits)
local all_delimiters = [[!"#$%&'*+,-./:;<=>?^_`|~()[]{}0123456789]]
-- specify a function for processing N-part of the string
local function convert(N_substring)
return N_substring:upper()
end
-- Now do the processing
local s = [[
fld u.a. ldfjal \verb{u.a.{ dlf \lstinline{u.a.} u.a. dfla
\url{u.a.}rrr \@Some@Macros~u.a.~{u.a.}{u.a.}qq\verb|\lstinline+nested use+qqq|q
]]
s = s:gsub("\\([%a@]+)",
function(macro_name)
if all_macros[macro_name] then
return
"\1\\"..macro_name
..(all_macros[macro_name] < 0 and "\2" or "\3")
:rep(math.abs(all_macros[macro_name]) + 1)
end
end
)
repeat
local old_length = #s
repeat
local old_length = #s
s = s:gsub("\2(\2+)(%b{})", "%2%1")
until old_length == #s
s = s:gsub("[\2\3]([\2\3]+)((["..all_delimiters:gsub("%p", "%%%0").."])(.-)%3)", "%2%1")
until old_length == #s
s = ("\2"..s.."\1"):gsub("[\2\3]+([^\2\3]-)\1", convert):gsub("[\1\2\3]", "")
-- Print the result
print(s)
Run Code Online (Sandbox Code Playgroud)
输出:
FLD U.A. LDFJAL \verb{u.a.{ DLF \lstinline{u.a.} U.A. DFLA
\url{u.a.}RRR \@Some@Macros~u.a.~{u.a.}{U.A.}QQ\verb|\lstinline+nested use+qqq|Q
Run Code Online (Sandbox Code Playgroud)