Как удалить последнюю строку из строки в Lua?

#lua #world-of-warcraft

#lua #world-of-warcraft

Вопрос:

Я использую Lua в World of Warcraft.

У меня есть эта строка:

 "Thisnisnmynlife."
  

Итак, при печати выводится следующее:

 This
is
my
life.
  

Как я могу сохранить всю строку, кроме последней строки, в новой переменной?

Итак, я хочу, чтобы вывод новой переменной был таким:

 This
is
my
  

Я хочу, чтобы код Lua находил последнюю строку (независимо от того, сколько строк в строке), удалял последнюю строку и сохранял оставшиеся строки в новой переменной.

Спасибо.

Комментарии:

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

2. Это здорово, Егор. Можете ли вы сказать мне, как сохранить первую строку old_str в new_str тоже?

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

4. Спасибо, Егор. Я хотел бы отметить это как правильный ответ, но я не могу отметить комментарий. Если вы хотите поместить свои ответы в ответ, я отмечу его как правильный.

5. new_str = old_str:gsub("n[^n]*(n?)$", "%1") решит проблему, описанную @exnihilo

Ответ №1:

Итак, я обнаружил, что решения Егора Скриптунова в комментариях действительно работали очень хорошо, но я не могу пометить его комментарии как ответ, поэтому я помещу его ответы здесь.

При этом удаляется последняя строка, а оставшиеся строки сохраняются в новой переменной:

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

Если в конце последней строки есть маркер новой строки, Егор опубликовал это как решение:

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

При этом первая строка удаляется, а остальные строки сохраняются в новой переменной:

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

Спасибо за помощь, Егор.

Ответ №2:

Наиболее эффективным решением является обычная string.find.

 local s = "Thisnisnmynlife." -- string with newlines
local s1 = "Thisismylife." -- string without newlines

local function RemoveLastLine(str)
    local pos = 0 -- start position
    while true do -- loop for searching newlines
        local nl = string.find(str, "n", pos, true) -- find next newline, true indicates we use plain search, this speeds up on LuaJIT.
        if not nl then break end -- We didn't find any newline or no newlines left.
        pos = nl   1 -- Save newline position,   1 is necessary to avoid infinite loop of scanning the same newline, so we search for newlines __after__ this character
    end
    if pos == 0 then return str end -- If didn't find any newline, return original string

    return string.sub(str, 1, pos - 2) -- Return substring from the beginning of the string up to last newline (- 2 returns new string without the last newline itself
end

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

Имейте в виду, что это работает только для строк с n символами новой строки, если у вас есть nr , или rn более простым решением будет шаблон.

Это решение эффективно для LuaJIT и для длинных строк. Для маленьких строк string.sub(s1, 1, string.find(s1,"n[^n]*$") - 1) это нормально (не на LuaJIT tho).

Ответ №3:

Я сканирую ее назад, потому что проще удалить что-то из back с помощью обратного сканирования, а не вперед, было бы сложнее, если бы вы сканировали вперед и намного проще сканировали назад

Я преуспеваю в этом за один дубль

 function removeLastLine(str) --It will return empty string when there just 1 line
  local letters = {}
  for let in string.gmatch(str, ".") do --Extract letter by letter to a table
    table.insert(letters, let)
  end

  local i = #letters --We're scanning backward
  while i >= 0 do --Scan from bacward
    if letters[i] == "n" then
      letters[i] = nil
      break
    end
    letters[i] = nil --Remove letter from letters table
    i = i - 1
  end
  return table.concat(letters)
end

print("Thisnisnmynlife.")
print(removeLastLine("Thisnisnmynlife."))
  

Как работает код

  1. Буквы в str аргументе будут извлечены в таблицу ( "Hello" станут {"H", "e", "l", "l", "o"} )

  2. i local устанавливается в конец таблицы, потому что мы просматриваем ее от начала до конца

  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 что возвращает пустую строку, если таблица пуста

Ответ №4:

 #! /usr/bin/env lua

local serif = "Is this thenreal life?nIs thisnjust fantasy?"
local reversed = serif :reverse()  --  flip it

local pos = reversed :find( 'n' )  1  --  count backwards
local sans_serif = serif :sub( 1, -pos )  --  strip it

print( sans_serif )
  

вы можете выровнять ее, если хотите, те же результаты.

 local str = "Is this thenreal life?nIs thisnjust fantasy?"
print(  str :sub( 1,  -str :reverse() :find( 'n' ) -1 )  )
  

Is this the
real life?
Is this

Комментарии:

1. Не понижающий параметр, но это не удается для входных строк, которые не содержат символов новой строки.