如何在 Lua 中删除字符串的最后一行?

我在魔兽世界中使用 Lua。

我有这个字符串:

"This\nis\nmy\nlife."

因此,当打印时,输出如下:

This
is
my
life.

如何将整个字符串存储在一个新变量中,但排除最后一行?

因此,我希望新变量的输出如下所示:

This
is
my

我想要 Lua 代码查找最后一行(无论字符串中有多少行),删除最后一行并将剩余行存储在新变量中。

谢谢。

点赞
用户3342050
用户3342050
#! /usr/bin/env lua

local serif = "Is this the\nreal life?\nIs this\njust fantasy?"
local reversed = serif :reverse()  --  翻转它

local pos = reversed :find( '\n' ) +1  --  倒序计数
local sans_serif = serif :sub( 1, -pos )  --  去掉它

print( sans_serif )

如果你愿意,你可以把它压成一行,结果一样。

local str = "Is this the\nreal life?\nIs this\njust fantasy?"
print(  str :sub( 1,  -str :reverse() :find( '\n' ) -1 )  )

Is this the

real life?

Is this

2020-11-15 12:57:54
用户8621712
用户8621712

最高效的解决方案是使用纯字符串查找。

local s = "This\nis\nmy\nlife." -- 带有换行符的字符串
local s1 = "Thisismylife." -- 不带换行符的字符串

local function RemoveLastLine(str)
    local pos = 0 -- 起始位置
    while true do -- 寻找换行符的循环
        local nl = string.find(str, "\n", pos, true) -- 查找下一个换行符,true 表示我们使用纯查找,这在 LuaJIT 上会加速。
        if not nl then break end -- 没有找到换行符或没有剩余的换行符。
        pos = nl + 1 -- 保存换行符位置,+1 是必要的,以避免无限循环扫描相同的换行符,因此我们在该字符之后搜索新的换行符。
    end
    if pos == 0 then return str end -- 如果没有找到任何换行符,则返回原始字符串

    return string.sub(str, 1, pos - 2) -- 返回从字符串开头到最后一个换行符的子字符串(-2 返回没有最后一个换行符的新字符串)
end

print(RemoveLastLine(s))
print(RemoveLastLine(s1))

请记住,这只适用于具有 \n 样式换行符的字符串,如果您有 \n\r\r\n,更简单的解决方案是使用模式匹配。

对于 LuaJIT 和长字符串,此解决方案非常高效。 对于小字符串,string.sub(s1, 1, string.find(s1,"\n[^\n]*$") - 1) 就可以了(但在 LuaJIT 上不行)。

2020-11-15 18:45:21
用户10968197
用户10968197

所以我发现 Egor Skriptunoff 的解决方案在评论中非常有效,但是我无法将他的评论标记为答案,所以我会在此处放置他的答案。

这将删除最后一行并将剩余行存储在一个新变量中:

new_str = old_str:gsub("\n[^\n]*$", "")

如果在最后一行末尾有一个换行符,Egor 提供了以下解决方法:

new_str = old_str:gsub("\n[^\n]*(\n?)$", "%1")

而这将删除第一行,并将剩余行存储在一个新变量中:

first_line = old_str:match("[^\n]*")

感谢您的帮助,Egor。

2020-11-26 17:05:16
用户13447666
用户13447666

我将它反向扫描是因为在后面移除东西比前面更容易,如果你向前扫描,那么它会更复杂,而向后扫描会更简单。

我一次成功了

function removeLastLine(str) --当只有 1 行时,它将返回空字符串
  local letters = {}
  for let in string.gmatch(str, ".") do --逐个字母将其提取到一个表中
    table.insert(letters, let)
  end

  local i = #letters --我们从后往前扫描
  while i >= 0 do --从后往前扫描
    if letters[i] == "\n" then
      letters[i] = nil
      break
    end
    letters[i] = nil --从字母表中移除字母
    i = i - 1
  end
  return table.concat(letters)
end

print("This\nis\nmy\nlife.")
print(removeLastLine("This\nis\nmy\nlife."))

代码的工作原理

  1. 参数 str 中的字母将被提取到一个表中( "Hello" 将变成 {"H", "e", "l", "l", "o"})

  2. i 局部变量设置为表的末尾,因为我们将从后往前扫描

  3. 检查 letters[i] 是否是 \n 如果是,则转到步骤 7

  4. 删除 letters[i] 中的条目

  5. i 减 1

  6. 重复步骤 3 直到 i 为零,如果 i 为零,则转到步骤 8

  7. 移除 letters[i] 中的条目,因为在检查换行符时还没有移除

  8. 返回 table.concat(letters)。如果表为空,则不会导致错误,因为 table.concat 将返回空字符串

2020-11-27 02:38:46