Шаблоны Lua - World of Warcraft Vanilla

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

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

Функция gsub:
http://wowprogramming.com/docs/api/gsub < br> http://wowwiki.wikia.com/wiki/API_gsub

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

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

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

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

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

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

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

чат

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

Вопрос: как взять полный 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 модификатор может применяться только к классу символов; нет возможности группировать паттерны под модификатором. Например, нет шаблона, который соответствует необязательному слову (если слово не состоит только из одной буквы). Обычно вы можете обойти это ограничение, используя некоторые из продвинутых методов, которые мы увидим позже.

Источник.

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


person user7393973    schedule 10.02.2017    source источник
comment
Кажется, что каждый из этих потенциальных шаблонов заканчивается на s ago, так почему бы не сопоставить это? "^(.*s) ago". Также вы можете использовать match вместо gsub. Если вам нужно регулярное выражение для разделения строк на поля, переформатируйте свой вопрос, и я дам правильный ответ.   -  person ktb    schedule 11.02.2017
comment
@ktb, теперь, когда вы это говорите, я, наверное, не против получить 99d23h59m59s целиком. Не уверен, что match работает с игрой, я пробовал некоторые строковые функции, и единственные, которые я нашел работающими, были gsub и strfind. Если вы считаете, что это должно работать, дайте мне имя функции, потому что я не думаю, что соответствует работает.   -  person user7393973    schedule 11.02.2017
comment
Я не был знаком с модификациями добавленного базового языка WoW. Они добавили псевдонимы без пространства имен для определенных функций. Например, gsub на самом деле является псевдонимом для string.gsub, а также strmatch является псевдонимом для string.match, функции, о которой я имел в виду. И я считаю, что вам может потребоваться отредактировать свой вопрос, чтобы точно объяснить, что вы хотите сопоставить с этими строками. Из вашего примера я делаю вывод, что вы пытаетесь сопоставить дневную часть строки?   -  person ktb    schedule 11.02.2017
comment
@ktb, в конце вопрос отредактировал.   -  person user7393973    schedule 11.02.2017
comment
В той вики, на которую вы связались, есть целая статья о сопоставлении с образцом, я сам постоянно на нее ссылаюсь. wowwiki.wikia.com/wiki/Pattern_matching Хорошо объясняет, что делают волшебные персонажи.   -  person Alundaio    schedule 11.02.2017
comment
@Alundaio - Да, сейчас я пытаюсь все это выучить. Также проверяем это и this. Это слишком много информации, которую нужно усвоить, и она немного сбивает с толку, но я изо всех сил стараюсь ее понять.   -  person user7393973    schedule 11.02.2017


Ответы (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 }
person Frelling    schedule 13.02.2017

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. Напротив, мы знаем с абсолютной уверенностью порядок вывода.

person Alundaio    schedule 11.02.2017
comment
Это может быть способ заставить его работать, но сейчас я сосредоточусь на изучении того, могу ли я использовать шаблоны и захваты для получения дополнительных подстрок. - person user7393973; 11.02.2017
comment
@ user7393973 К сожалению, шаблоны Lua не поддерживают то, что, как я думаю, вам нужно. Это хорошее место для начала работы с шаблонами в Lua lua.org/manual /5.1/manual.html#5.4.1 - person ktb; 11.02.2017
comment
@ user7393973 Отредактировано, решение может быть более подходящим для ваших нужд. Одно совпадение с образцом. - person Alundaio; 11.02.2017