假设我有str变量,我为其赋值test\\ttest(或者它实际上只是\\,对于这种情况).我想要做的是用单反斜杠代替双反斜杠.
目的很明确:我想输出\t转义序列(水平制表符),而现在它只是输出为纯文本\t.
很明显,我不能使用:
str:gsub("\\","\")
Run Code Online (Sandbox Code Playgroud)
因为这会导致语法错误,被\"识别为转义序列.我尝试了所有可以出来的方式.我也尝试使用loadstring()(以及嵌套的loadstring()调用),但它也失败了.
请不要说:
str:gsub("\\t","\t")
Run Code Online (Sandbox Code Playgroud)
当然,它会起作用,但这不是我需要的.我需要用一个反斜杠替换双反斜杠.
我怀疑你被引用搞糊涂了,因为string.gsub可以替换反斜杠字符:
C:...> lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > a="test\\\\ttest" > =a test\\ttest > =a:gsub([[\\]],[[\]]) test\ttest 1 >
反斜杠在双引号和单引号字符串中用作字符转义,但在用[[...]]符号编写的长字符串中不能.在通常的字符串常量中,反斜杠使用一个或多个后续字符,并用内部字符串值中的单个字节替换整个序列.所以"\\"包含单个反斜杠的单字节字符串"\"是语法错误,并且"\""是包含双引号的单字节字符串.
令人困惑的是,string.gsub(和它的兄弟姐妹)所理解的Lua模式使用%字符来引用和命名特殊模式.这是Lua模式与其他语言支持的正则表达式之间更明显的差异之一.对于Lua模式,反斜杠只是一个普通的字符.
因此,当我设置a上面的值时,我使用额外的反斜杠来获取总共两个字符串值.我本来可以写a=[[test\\ttest]]同样的效果.调用gsub是用简单的模式编写的,用单个替换双倍的反斜杠.可以看出,它成功了,结果是字符串test\ttest(以及匹配计数作为第二个返回值).
简而言之,您在问题中所要求的替换"正常运作"如预期的那样.
但是在线之间阅读,这并不是你想要的.您似乎正在尝试将字符串转换test\\ttest为test<TAB>test.如果单个转换是你想要的,那么就这样写: a:gsub([[\\t]],"\t").(请注意,我使用了引号,以便字符串文字将其解释\t为替换值中的ASCII字符.)
更一般的情况更难,因为您不仅需要处理tab,bell,backspace,回车符,换行符等正常的单字母转义符,而且还必须处理一到三位十进制代码序列.
更新:编写一些处理所有反斜杠转义的东西的诱惑,因为Lua编译器为字符串文字做的事情证明太强了.
function unbackslashed(s)
local ch = {
["\\a"] = '\\007', --'\a' alarm Ctrl+G BEL
["\\b"] = '\\008', --'\b' backspace Ctrl+H BS
["\\f"] = '\\012', --'\f' formfeed Ctrl+L FF
["\\n"] = '\\010', --'\n' newline Ctrl+J LF
["\\r"] = '\\013', --'\r' carriage return Ctrl+M CR
["\\t"] = '\\009', --'\t' horizontal tab Ctrl+I HT
["\\v"] = '\\011', --'\v' vertical tab Ctrl+K VT
["\\\n"] = '\\010',-- newline
["\\\\"] = '\\092',-- backslash
["\\'"] = '\\039', -- apostrophe
['\\"'] = '\\034', -- quote
}
return s:gsub("(\\.)", ch)
:gsub("\\(%d%d?%d?)", function(n)
return string.char(tonumber(n))
end)
end
Run Code Online (Sandbox Code Playgroud)
如果解析用户提供的文本并希望在用户提供的文本中处理反斜杠转义,则这样的函数可能会很有用.字符串文字应该由编译器处理.
另一个警告是,如果你发现自己有部分翻译的字符串,你实际上可能会缺乏设计的清晰度.实际上在解析用户输入之外需要这样的函数表明您的设计可能存在更深层次的问题.
该函数的unbackslashed工作原理是首先替换所有已识别的序列,这些序列采用反斜杠形式,后跟单个字符及其等效的数字形式.第二遍将所有数字形式转换为其文字字符.需要两次传递,因为理解的字符串模式string.gsub不支持完整正则表达式解析器支持的替代符号.否则,匹配的模式可能与Perl类似,/\\([0-9]{1-3})|\\(.)/并且在一次传递中执行替换.