【问题标题】:How does this detab function in Lua workLua 中的 detab 函数是如何工作的
【发布时间】:2013-08-01 10:54:07
【问题描述】:
-- Converts tabs to spaces
function detab(text)
    local tab_width = 4
    local function rep(match)
        local spaces = -match:len()
        print("match:"..match)
        while spaces<1 do spaces = spaces + tab_width end
        print("Found "..spaces.." spaces")
        return match .. string.rep(" ", spaces)
    end
    text = text:gsub("([^\n]-)\t", rep)
    return text
end


str='   thisisa string'
--thiis is a      string

print("length: "..str:len())
print(detab(str))
print(str:gsub("\t","    "))

我有一段来自 markdown.lua 的代码,可以将制表符转换为空格(顾名思义)。
我设法弄清楚的是它从一开始就搜索 直到找到一个选项卡并将匹配的子字符串传递给'rep' 函数。它会反复执行此操作,直到没有更多匹配项为止。
我的问题是试图弄清楚 rep 函数在做什么,尤其是在 while 循环。
为什么循环会在 1 处停止?
为什么会计数?
令人惊讶的是,它统计了字符串中的空格数,究竟是个谜。
如果你将它的输出与最后一个gsub 替换的输出进行比较,你会发现它们是不同的。
Detab 维护 字符的对齐,而 gsub 替换没有。 为什么会这样?
额外问题。当我在 Scite 中打开空格时,我可以看到 't' 之前的标签比之前的标签长第三个's'它们为什么不同?

【问题讨论】:

  • 函数rep(match)中的spaces计算的等效形式没有循环:local spaces = tab_width - #match % tab_width

标签: tabs lua spaces


【解决方案1】:

通过分析rep 函数,这似乎是它正在做的事情。首先,它获取传入的匹配字符串的长度并将其设为负数(例如,将其乘以 -1)。在 while 循环中,它会不断增加空间,直到变为正数。

使用数字线可能更容易将其可视化:

<--|----|-------|----|----|----|----|----|----|----|----|--->
  -n      -spaces             -2   -1    0    1    2    n

本质上,循环试图在“溢出”之前计算有多少“tab_width”可以放入空格。这里它使用从 0 到 1 的过渡作为截止点。在循环之后,spaces 会有多少溢出。

事实上,while 循环正在模仿一种数学运算,您可能知道它是取模。换句话说,内部的rep 函数可以重写为:

local function rep(match)
  local spaces = tab_width - match:len() % tab_width

  return match .. string.rep(" ", spaces)
end

这与外部str:gsub("\t", " ") 不同,后者不加选择地 将所有制表符替换为4 个空格。 OTOH,在detab 函数中,替换制表符的空格数取决于匹配捕获的长度。

eg.
matching length is 1, replace tab with 3 spaces
matching length is 2, replace tab with 2 spaces
matching length is 3, replace tab with 1 space
matching length is n, replace tab with tab_width - (n % tab_width) spaces
etc.

【讨论】:

  • 你的意思是不分青红皂白吗?
【解决方案2】:

要回答奖金问题: 制表符与制表位对齐。一个制表位是八个字符。第一个制表符从第六列开始,因此需要填充三个空格。第二个选项卡从第 16 列开始,因此它只需要一个空格宽。

当空格变为正数时循环停止,因为循环一直在“缩进”增量中添加空格,直到它有足够的空格比匹配的文本更长。然后,当它将该数量的空格与匹配的文本组合时,它构建了一个字符串,该字符串被填充到正确的制表位。

这也是 gsub 不同的原因。 gsub 不将制表符视为制表位字符,而是将其视为四个空格。所以第二个制表符不会填充到制表位,而是扩展为四个空格。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2022-06-10
    • 2022-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多