Lua 'простой' string.gsub

Я наткнулся на небольшой блок с разбором строки. У меня есть строка вроде:

footage/down/temp/cars_[100]_upper/cars_[100]_upper.exr

и у меня возникли трудности с использованием gsub для удаления части строки. Обычно я бы сделал это

lineA = footage/down/temp/cars_[100]_upper/cars_[100]_upper.exr
lineB = footage/down/temp/cars_[100]_upper/
newline = lineA:gsub(lineB, "")

который обычно дает мне 'cars_[100]_upper.exr'

Проблема в том, что gsub не любит [] или другие специальные символы в строке и, в отличие от string.find, gsub не имеет возможности использовать флаг «plain» для отмены поиска по шаблону.

Я не могу вручную редактировать строки, чтобы включить escape-символы для специальных символов, поскольку я делаю файл сценария сравнения файлов.

Любая помощь в переходе от lineA к новой строке с использованием lineB будет очень признательна.


person user212458    schedule 16.11.2009    source источник


Ответы (3)


Взято со страницы 181 программирования в Lua 2e:

Волшебные персонажи:

( ) . % + - * ? [ ] ^ $

Символ '%' работает как побег для этих магических символов.

Итак, мы можем просто придумать простую функцию для экранирования этих магических символов и применить ее к вашей входной строке (lineB):

function literalize(str)
    return str:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", function(c) return "%" .. c end)
end

lineA = "footage/down/temp/cars_[100]_upper/cars_[100]_upper.exr"

lineB = literalize("footage/down/temp/cars_[100]_upper/")

newline = lineA:gsub(lineB, "")

print(newline)

Что, конечно же, печатает: cars_[100]_upper.exr.

person Mark Rushakoff    schedule 17.11.2009
comment
Другой (вероятно, более быстрый) способ буквального написания: str:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0") - person catwell; 19.11.2012
comment
ОТЛИЧНЫЙ подход. Примечание: да, шаблоны lua часто мешают. 'Мощный'. Как насчет полезного? - person Henrik Erlandsson; 31.07.2014

Вы можете использовать другой подход, например:

local i1, i2 = lineA:find(lineB, nil, true)
local result = lineA:sub(i2 + 1)
person Kknd    schedule 16.11.2009
comment
Просто поместите это в цикл, пока find не вернет ненулевое значение, чтобы соответствовать тому, что gsub заменяет все вхождения шаблона. - person sbk; 17.11.2009
comment
Это тоже не работает, потому что и в string.find магические символы считаются таковыми (см. следующий ответ ниже). - person Gert; 20.09.2010
comment
Передача true в качестве четвертого параметра (self, pattern, init, plain) заставляет функцию игнорировать магические символы в шаблоне. - person Kknd; 28.12.2010

Вы также можете избежать знаков препинания в текстовой строке str, используя:

str:gsub ("%p", "%%%0")

person Stomp    schedule 19.11.2012