Выкройки Луа - World of Warcraft Vanilla

Я пытаюсь получить некоторые данные из чата игры, но не могу понять схему.

Это для дополнения для World of Warcraft Vanilla (частный сервер).

функция gsub:
http://wowprogramming.com/docs/api/gsub
http://wowwiki.wikia.com/wiki/API_gsub

Я хорошо справлялся с этим объяснением, но теперь есть часть, где у меня есть что-то вроде этого:

variable = gsub(string, "([%d+d]+)?...", "")

Я не знаю, каким должен быть шаблон, поскольку строка может быть похожа на один из следующих примеров:

2d17h6m31s
1d8h31m40s
22h40m4s
8h6m57s
5m25s
37s

"([%d+d]+)?" на самом деле несколько попыток моей положить вместе.

Я читал о магических персонажах ( ) . % + - * ? [ ^ $ но есть еще кое-что, чего я не понимаю. Если бы я мог получить простое объяснение резюме, было бы здорово!

Важная часть того, как выглядит чат:

чат

Изменить ( комментарий КТБ):

Вопрос: как мне взять полный "99d23h59m59s" (^(.*s) не сделал трюк)?

В 99d23h59m59s, 99 может быть от 1 до 99 и всегда имеет d сразу после, но это необязательно, если есть на самом деле <number>d или нет. То же самое <number>h (диапазон номеров от 1 до 24), <number>m (диапазон номеров от 1 до 59). Всегда есть ago в конце.

Обновить:

/run for key in pairs(string)do ChatFrame1:AddMessage(key)end

С помощью этой команды я получил имена всех функций string.functionName()вот список:

string.sub ()

string.gfind ()

string.rep ()

string.gsub ()

string.char ()

string.dump ()

string.find ()

string.upper ()

string.len ()

String.Format ()

string.byte ()

string.lower ()

Обновление информации:

В отличие от некоторых других языков сценариев, Lua не использует регулярные выражения POSIX (regexp) для сопоставления с образцом. Основной причиной этого является размер: типичная реализация регулярного выражения POSIX занимает более 4000 строк кода. Это больше, чем все стандартные библиотеки Lua вместе взятые. Для сравнения, реализация сопоставления с образцом в Lua имеет менее 500 строк. Конечно, сопоставление с образцом в Lua не может сделать все, что делает полная реализация POSIX. Тем не менее, сопоставление с образцом в Lua является мощным инструментом и включает в себя некоторые функции, которые трудно сопоставить со стандартными реализациями POSIX.

Источник

В отличие от некоторых других систем, в Lua модификатор может применяться только к классу символов; нет способа группировать шаблоны под модификатором. Например, не существует шаблона, который соответствует необязательному слову (если только слово не содержит только одну букву). Обычно вы можете обойти это ограничение, используя некоторые передовые методы, которые мы увидим позже.

Источник

Я не могу найти "продвинутые методы", сказанные в цитате выше. Я нашел только то, в чем я еще не уверен.

2 ответа

Решение

Несколько лет назад я столкнулся с такими же шаблонными ограничениями из-за аддона WoW. Потребовалось немного поиска, но я откопал свою функцию разбора.

parse_duration.lua

--
-- string:parseDuration() - parse a pseudo ISO-8601 duration of the form
-- [nd][nh][nm][ns], where 'n' is the numerical value of the time unit and
-- suffix designates time unit as follows: 'd' - days, 'h' - hours,
-- 'm' - minutes, and, 's' - seconds. Unspecified time units have a value
-- of 0.
--

function string:parseDuration()
  local ts = {d=0, h=0, m=0, s=0}
  for v in self:lower():gfind("%d+[dhms]") do
    ts[v:sub(-1)] = tonumber(v:sub(1,-2))
  end

  return ts
end

Следующее тестирует ваши образцы данных.

duration_utest.lua

require "parse_duration"

local function main()
  local testSet = {
    "2d17h6m31s ago something happened",
    "1d8h31m40s ago something happened",
    "22h40m4s ago something happened",
    "8h6m57s ago something happened",
    "5m25s ago something happened",
    "37s ago something happened",
    "10d6s alias test 1d2h3m4s should not be parsed"
  }

  for i,testStr in ipairs(testSet) do
    -- Extract timestamp portion
    local tsPart = testStr:match("%S+")
    local ts = tsPart:parseDuration()

    io.write( tsPart, " -> { ")
    for k,v in pairs(ts) do
      io.write(k,":",v," ")
   end
    io.write( "}\n" )
  end
end

main()

Результаты

2d17h6m31s -> { m:6 d:2 s:31 h:17 }
1d8h31m40s -> { m:31 d:1 s:40 h:8 }
22h40m4s -> { m:40 d:0 s:4 h:22 }
8h6m57s -> { m:6 d:0 s:57 h:8 }
5m25s -> { m:5 d:0 s:25 h:0 }
37s -> { m:0 d:0 s:37 h:0 }
10d6s -> { m:0 d:10 s:6 h:0 }
function get_time_stamp(str)
    local s,m,h,d = string.match(str:reverse(),"oga s(%d*)m?(%d*)h?(%d*)d?(%d*)")
    return d and d:reverse() or 0, h and h:reverse() or 0, m and m:reverse() or 0, s and s:reverse() or 0
end 
local day,hour,minute,second = get_time_stamp("2d17h6m31s ago")
print (day,hour,minute,second) -- output: 2 17 6 31

day,hour,minute,second = get_time_stamp("5m25s ago")
print (day,hour,minute,second) -- output: 0 0 5 25

Если вам интересно, почему я использую реверс, это потому, что мы точно знаем, что секунда всегда будет существовать, но другие не будут, если мы не будем использовать реверс, мы не узнаем, в каком порядке находятся числа при выводе в виде строки. матч. Вот пример того, что я имею в виду, если вы сделали local d,h,m,s = string.match("5m25s ago","(%d*)d?(%d*)h?(%d*)m?(%d+)s ago") Тогда print(d,h,m,s) скажет, что дни были 5, а секунды были 25. Обратно мы знаем с абсолютной уверенностью порядок вывода.

Другие вопросы по тегам