В Lua, я пытаюсь сопоставить образ и захватить:
+384 Critical Strike (Reforged from Parry Chance)
а
(+384) (Critical Strike)
где суффикс (Reforged from %s)
является необязательным.
Длинная версия
Я пытаюсь сопоставить строку в Lua, используя шаблоны (т.е. strfind
)
Примечание. В Lua они не называют их регулярными выражениями, они называют их шаблонами, потому что они не regular.
Примеры строк:
+384 Critical Strike
+1128 Hit
Это разбивается на две части, которые я хочу захватить:
- Число с лидирующим положительным или отрицательным индикатором; int его случай
+384
- Строка в этом случае
Critical Strike
.
Я могу захватить их, используя довольно простой шаблон:
И этот шаблон в lua работает:
local text = "+384 Critical Strike";
local pattern = "([%+%-]%d+) (.+)";
local _, _, value, stat = strfind(text, pattern);
- value =
+384
- stat =
Critical Strike
Трудная часть
Теперь Мне нужно расширить этот шаблон регулярного выражения, чтобы включить дополнительный суффикс:
+384 Critical Strike (Reforged from Parry Chance)
Что разбивается на:
Примечание: Мне не особо интересен дополнительный суффикс суффикса; это означает, что у меня нет требования, чтобы захватить его, хотя захват был бы удобным.
Здесь я начинаю сталкиваться с проблемами с жадным захватом. Сразу же у шаблона у меня уже есть то, что я не хочу:
- pattern =
([%+%-]%d+) (.+)
- value =
+384
- stat =
Critical Strike (Reforged from Parry Chance)
Но попробуйте включить суффикс в шаблон:
с рисунком:
pattern = "([%+%-]%d+) (.+)( %(Reforged from .+%))?"
И я использую оператор ?
для указания появления 0
или 1
суффикса, но который соответствует ничего.
Я слепо попытался изменить необязательную суффиксную группу из скобки (
в скобки [
:
pattern = "([%+%-]%d+) (.+)[ %(Reforged from .+%)]?"
Но теперь матч снова жадный:
- value =
+384
- stat =
Critical Strike (Reforged from Parry Chance)
На основе ссылка на шаблон Lua):
- x: (где x не является одним из магических символов ^ $()%. [] * + -?) представляет сам символ x.
- .: (точка) представляет все символы.
- % a: представляет все буквы.
- % c: представляет все управляющие символы.
- % d: отображает все цифры.
- % l: представляет все строчные буквы.
- % p: представляет все символы пунктуации.
- % s: представляет все пробельные символы.
- % u: отображает все прописные буквы.
- % w: отображает все буквенно-цифровые символы.
- % x: представляет все шестнадцатеричные цифры.
- % z: представляет символ с представлением 0.
- % x: (где x - любой не-буквенно-цифровой символ) представляет символ x. Это стандартный способ избежать волшебных персонажей. Каждому знаку пунктуации (даже не магическому) может предшествовать символ "%", когда он используется для представления себя в шаблоне.
- [set]: представляет класс, который является объединением всех символов в наборе. Ряд символов может быть задан путем разделения концевых символов диапазона на "-". Все классы% x, описанные выше, также могут использоваться как компоненты в наборе. Все остальные символы в наборе представляют себя. Например, [% w_] (или [_% w]) представляет все буквенно-цифровые символы плюс подчеркивание, [0-7] представляет восьмеричные цифры, а [0-7% l% -] представляет восьмеричные цифры плюс нижний регистр буквы плюс символ "-". Взаимодействие между диапазонами и классами не определено. Поэтому шаблоны, такие как [% a-z] или [a - %%], не имеют никакого значения.
- [^ set]: представляет дополнение к множеству, где set интерпретируется, как указано выше.
Для всех классов, представленных одиночными буквами (% a,% c и т.д.), соответствующая прописная буква представляет дополнение к классу. Например,% S представляет все непространственные символы.
Определения букв, пробелов и других групп символов зависят от текущей локали. В частности, класс [a-z] не может быть эквивалентен% l.
и волшебные матчи:
-
*
, который соответствует 0 или более повторениям символов в классе. Эти элементы повторения всегда будут соответствовать максимально возможной последовательности; -
+
, который соответствует 1 или более повторениям символов в классе. Эти элементы повторения всегда будут соответствовать максимально возможной последовательности; -
-
, который также соответствует 0 или более повторениям символов в классе. В отличие от '*', эти элементы повторения всегда будут соответствовать кратчайшей последовательности; -
?
, который соответствует 0 или 1 появлению символа в классе;
Я заметил, что есть жадный *
и неживый модификатор -
. Поскольку мой средний совпадчик строк:
(%d) (%s) (%s)
кажется, поглощает текст до конца, возможно, я должен попытаться сделать его неживым, изменив *
на -
:
oldPattern = "([%+%-]%d+) (.*)[ %(Reforged from .+%)]?"
newPattern = "([%+%-]%d+) (.-)[ %(Reforged from .+%)]?"
Кроме того, он не соответствует:
- value =
+384
- stat = nil
Вместо того, чтобы средняя группа захватывала "любой" символ (т.е. .
), я попробовал набор, содержащий все, кроме (
:
pattern = "([%+%-]%d+) ([^%(]*)( %(Reforged from .+%))?"
и оттуда колеса сошли с фургона:
local pattern = "([%+%-]%d+) ([^%(]*)( %(Reforged from .+%))?"
local pattern = "([%+%-]%d+) ((^%()*)( %(Reforged from .+%))?"
local pattern = "([%+%-]%d+) (%a )+)[ %(Reforged from .+%)]?"
Я думал, что я был близок с:
local pattern = "([%+%-]%d+) ([%a ]+)[ %(Reforged from .+%)]?"
который фиксирует
- value = "+385"
- stat = "Critical Strike " (notice the trailing space)
Итак, вот где я ударяю головой о подушку и ложись спать; Я не могу поверить, что провел четыре часа в этом регулярном выражении.... pattern.
@NicolBolas. Набор всех возможных строк, определенных с использованием псевдорегулярного языка выражений, следующий:
+%d %s (Reforged from %s)
где
-
+
представляет либо знак плюса (+
), либо "Минус-знак" (-
) -
%d
представляет любой символ латинской цифры (например,0..9
) -
%s
представляет любые латинские прописные или строчные буквы или встроенные пробелы (например,A-Za-z
) - остальные символы являются литералами.
Если бы мне пришлось писать регулярное выражение, которое явно пытается сделать то, что я хочу:
\+\-\d+ [\w\s]+( \(Reforged from [\w\s]+\))?
Но я могу дать вам практически полный список всех значений, с которыми я, вероятно, столкнусь в дикой природе, если я не объясню это достаточно хорошо.
-
+123 Parry
положительное число, одно слово -
+123 Critical Strike
положительное число, два слова -
-123 Parry
отрицательное число, одно слово -
-123 Critical Strike
отрицательное число, два слова -
+123 Parry (Reforged from Dodge)
положительное число, одно слово, необязательный суффикс с одним словом -
+123 Critical Strike (Reforged from Dodge)
положительное число, два слова, необязательный суффикс с двумя словами -
-123 Parry (Reforged from Hit Chance)
отрицательное число, одно слово, необязательный суффикс, содержащий два слова -
-123 Critical Strike (Reforged from Hit Chance)
отрицательное число, два слова, необязательный суффикс с двумя словами
Есть бонус шаблоны, казалось бы, что шаблоны также будут соответствовать:
-
+1234 Critical Strike Chance
четырехзначное число, три слова -
+12345 Mount and run speed increase
пятизначное число, пять слов -
+123456 Mount and run speed increase
шестизначное число, пять слов -
-1 MoUnT aNd RuN sPeEd InCrEaSe
однозначное число, пять слов -
-1 HiT (Reforged from CrItIcAl StRiKe ChAnCe)
отрицательное однозначное число, одно слово, необязательный суффикс, содержащий 3 слова
И хотя идеальный шаблон должен соответствовать вышеуказанным бонусным записям, он не должен.
Локализация
В действительности все "числа", которые я пытаюсь проанализировать, будут локализованы, например:
-
+123,456
на английском языке (en-US) -
+123.456
в Германии (de-DE) -
+123'456
на французском языке (fr-CA) -
+123 456
на эстонском языке (et-EE) -
+1,23,456
в Assamese (as-IN)
Любой ответ должен не пытаться учесть эти проблемы локализации. Вы не знаете локаль, из которой будет представлен номер, поэтому локализация номера была удалена из вопроса. Вы должны строго предполагать, что числа содержат plus sign
, hyphen minus
и латинские цифры 0
через 9
. Я уже знаю, как разбирать локализованные числа. Этот вопрос связан с попыткой сопоставить необязательный суффикс с жадным шаблоном анализатора.
Изменить. Вам действительно не пришлось пытаться обрабатывать локализованный номер. На некотором уровне, пытаясь справиться с ними, не зная языковой стандарт, это неправильно. Например, я не включил все возможные локализации чисел. Для другого: я не знаю, какие будущие локализации могут существовать в будущем.