MyDC.ru _ Программирование на Lua _ Несколько Слов О Захватах И Регулярных Выражениях
Автор: Setuper 7.8.2008, 15:54
Итак, я думаю многие сталкивались в скриптах со всевозможными "захватами" и регулярными выражениями. Почти в каждом скрипте они встречаются.
Сразу же начну с нескольких примеров:
Код
local s, e, a, b, c, d = string.find("11.12.13.14", "^(%d+)%.(%d+)%.(%d+)%.(%d+)$") local _, _, a, b, c, d = string.find("11.12.13.14 ", "^(%d+)%.(%d+)%.(%d+)%.(%d+)$") local _, _, a, b, c, d = string.find("10 11.12.13.14 15", "(%d+)%.(%d+)%.(%d+)%.(%d+)") local _, _, a = string.find("Hello world", "%S+%s(%S+)") local _, _, a, b, c = string.find("<User> !massmsg hello world", "%b<>%s+(%S)(%S+)%s*(.*)")
Можете ли вы сказать, что тут выполняется??? Если не можете, то слушайте дальше...
Сначала расскажу, что такое захват, и что такое регулярное выражение. Формально, захват - это нахождение определённый последовательности символов и помещение их в переменную. Например, возьмём один из примеров, который я написал сверху:
Код
local s, e, a, b, c, d = string.find("11.12.13.14", "^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
этот пример - типичный пример захвата. Функция string.find "захватывает" из строки "11.12.13.14" определённую последовательность символов. Выражение "^(%d+)%.(%d+)%.(%d+)%.(%d+)$", называется РЕГУЛЯРНЫМ ВЫРАЖЕНИЕМ. в скобках указываются захваты, то есть тут 4 захвата. Из этой функции данные у нас заносятся в 6 локальных переменных, а именно s, e, a, b, c, d. В переменную s (s от слова start) заносится начальная позиция захвата, равная 1. У нас строка "11.12.13.14" имеет 11 символов, следовательно 11 позиций. В переменную e (e от слова end) заносится конечная позиция захвата, равная 11. Обычно, в скриптах эти позиции не нужны, тогда, обычно, переменные обозначают одним именем (для сохранения памяти), обычно, обозначают как "_" (чтобы эта переменная была не столь заметна). Далее в переменные a, b, c, d, соответственно, заносятся захваты (то, что захватывается скобками). Разберём регулярное выражение: "^(%d+)%.(%d+)%.(%d+)%.(%d+)$". Символ ^ означает, что следующее действие в регулярном выражении должно быть в начале строки. У нас следующее за символом ^ действие - это захват (%d+), следовательно, захват у нас должен выполняться обязательно с начала строки. Сейчас объясню более понятно на примерах. Возьмём два регулярных выражения "^(%d+)" и "(%d+)". Теперь с помощью действий:
Код
local s, e, a1 = string.find("11.12.13.14", "^(%d+)") local s, e, a2 = string.find("11.12.13.14", "(%d+)")
в переменные a1 и a2 запишутся данные: a1="11" и a2="11". Теперь изменим исходную строку (дописав вначале строки пробел):
Код
local s, e, a1 = string.find(" 11.12.13.14", "^(%d+)") local s, e, a2 = string.find(" 11.12.13.14", "(%d+)")
смотрим, что в переменных: a1=nil и a2="11". Теперь я думаю вам почти понятно в чем вся фишка, осталось только объяснить, что такое (%d+). (%d+) - это захват числа. Во второй строке вначале стоял пробел, поэтому выражение ^(%d+) не могло захватить число вначале строки, поэтому и функция string.find вернула nil, и записала в переменные s=nil, e=nil, a1=nil, а функция string.find(" 11.12.13.14", "(%d+)") записала в переменные s=1, e=2, a2="11". Заметьте, что хоть мы и захватываем число, но тем не менее оно является строковым числом "11", а не просто 11 !!!!!!!!. Аналогично дело обстоит с символом $, но только для конца строки. Таким образом, мы рассмотрели 3 первых примера, которые я предложил вначале. В первом примере: s=1, e=11, a="11", b="12", c="13", d="14" и захват происходит именно 4 чисел, разделённых точками, и никакой другой комбинации Во втором: _=nil, a=nil, b=nil, c=nil, d=nil и захвата не произошло из-за пробела в конце. В третьем: _=14, a="11", b="12", c="13", d="14" захват 4 чисел, разделённых точками, в любом месте (хоть вначале строки, хоть в середине, хоть в конце), и строка не обязана содержать только 4 числа, разделённых точками, в отличие от первых двух примеров.
Идём далее. Выпишу основные регулярные выражения:
Цитата
. - любой символ %a - латинская буква %с - контрольный символ %d - десятичная цифра %u - латинская буква верхнего регистра %l - латинская буква нижнего регистра %p - знак пунктуации %s - символ пробела %w - латинская буква или арабская цифра %z - нулевой символ
%A - не латинская буква %C - не контрольный символ %D - не десятичныая цифра %U - не латинская буква верхнего регистра %L - не латинская буква нижнего регистра %P - не знак пунктуации %S - не символ пробела %W - не латинская буква и не арабская цифра %Z - не нулевой символ
в 4 и 5 примерах встречается регулярное выражение %S. Находим в списке выше, и видим: %S - не символ пробела. То есть, это означает, что это не пробел, а следовательно это любой символ, кроме пробела.
Теперь рассмотрим всякие плюсики. Я буду рассматривать их совместно с регулярным выражением %s, то есть с символом пробела.
Цитата
%s - 1 символ пробела %s+ - 1 или более символов пробела %s- - 0 или более символов пробела %s* - 0 или более символов пробела %s? - 0 или 1 символ пробела
Теперь объясню разницу между * и - Удобнее всего на следующем примере. Я уже рассказал, что означает точка (смотри выше в списке регулярных выражений: "." - любой символ). Рассмотрим примеры следующих регулярных выражений:
Цитата
"(.*)" - захват всей строки "/(.*)/" - захват всего, что находится между КРАЙНИМИ символами / "/(.-)/" - захват всего, что находится между ПЕРВЫМИ ДВУМЯ символами /
Цитата
%bxy - нахождение, а в случае захвата и захват, всего того, что находится между символами x и y, включая концы x и y
Ну и последнее...
А если, допустим, я хочу захватить точку. Как быть? Дело в том, что точка является так называемым магическим символом. Магические символы: ( ) . % + - * ? [ ] ^ $ Перед всеми магическими символами нужно ставить %, то есть все магические символы надо экранировать. Таким образом, чтобы захватить точку надо написать "(%.)"
На последок ещё несколько часто используемых регулярных выражений:
Цитата
"(%S)" - захват первого не пробельного символа строки; "(%S*)" - захват первого слова или пустого слова ""; "%S*%s*(%S*)" - захват второго слова; "(%S*)%s*(%S*)" - захват первого и второго слова; "(%S%S)" - захват первых двух не пробельных символов; "(%S+)%s*(%d*)" - захват слова и числа; "(%d*%.%d*%.%d*%.%d*)" - захват строки из 4 чисел, разделенных точками (например ip адреса); "%s*(%d*%.%d*%.%d*%.%d*)%s*(%d*)%s*(.*)" - захват чисел, разделенных точками, захват числа, захват всего оставшегося; "()" - захват номера позиции; "(why)" - захват слова why (в любом месте); "^(why)" - захват слова why, только если оно стоит на первых трех (в данном случае) позициях; "(why)$" - захват слова why, только если оно стоит на последних трех (в данном случае) позициях; "%b<>%s+(%S)(%S+)%s*(.*)" - захват первого символа, сразу после текста, ограниченного символами < >, второй захват слова сразу после захваченного символа, третий захват - захват всего оставшегося. [^/]+ - не пустой захват с начала до символа /
Теперь, я думаю, что вы и сами сможете написать, что же получается в примерах 4 и 5???
Автор: district 10.11.2008, 9:34
Уф, суще дельный и юсфульный топик, заслуживает самого пристального изучения, исключительно на трезвую голову и после хорошего здорового сна Спасибо
Автор: Setuper 6.8.2009, 11:19
Это конечно же не относится к регулярным выражениям, однако очень часто используется до захвата данных.
Речь идёт о методе sub (или функции string.sub). Данный метод (функция) служит для обрезания строк или для выделения подстрок.
Код
sData = sData:sub(s, e)
В переменную sData будет возвращена подстрока строки sData начиная с позиции s и заканчивая позицией e. s и e могут быть также отрицательными. В случае когда они положительные, всё понятно, например sData:sub(3, 6). Тут этот метод возьмёт из sData с третьего до шестого символа включительно. Если же sData:sub(-5, -2), то метод возьмёт из sData со второго до пятого символа включительно, но уже отсчёт позиций будет идти с конца строки. В этой функции последний параметр является необязательным, т.е. можно написать sData:sub(2), в этом случае последний параметр берётся по умолчанию -1. Если последний параметр равен -1 - это означает, что строка берётся до конца, в данном примере со второго символа и до конца.
Последний символ | мы не видим, но он есть, этот символ не выводится в чат, но позволяет скрипту определять конец строки, поэтому в случае использования кода sData:sub(1, -2) как раз таки мы избавляемся от этого символа, т.е. берём строку начиная с первого символа и, заканчивая вторым с конца, так как первый с конца это символ |.
А вообще, применяют чаще всего этот метод чтобы отсечь ник и символ | и оставить только данные, посылаемые в чат, вот так:
Код
sData = sData:sub(tUser.sNick:len() + 4, -2)
Автор: Nickolya 10.8.2009, 10:56
Мерси, а методы len и sub естественно быстрее чем match или find ?! Т.е. к примеру, берем строку "<Nick> lalalalala|", в ней нам нужен текст сообщения, ник нам известен, вот примерный код теста:
CODE
sData = "<Nick> lalalalala|" sNick = "Nick"
iBegin = os.clock() for i = 1, 1000000 do --sNeedData = sData:match("^%b<>%s(.*)|$") sNeedData = sData:sub(sNick:len() + 4, -2) end
--Core.SendToAll((os.clock() - iBegin).." secs with _match_ and data: "..sNeedData) Core.SendToAll((os.clock() - iBegin).." secs with sub and data: "..sNeedData)
А вот результат, сначала закоментированы 2е строки, 5 раз, потом первые:
Цитата
[11:52:22] 0.74899999999991 secs with _match_ and data: lalalalala [11:52:23] 0.71699999999998 secs with _match_ and data: lalalalala [11:52:25] 0.73300000000006 secs with _match_ and data: lalalalala [11:52:25] 0.73299999999995 secs with _match_ and data: lalalalala [11:52:26] 0.74900000000002 secs with _match_ and data: lalalalala [11:52:41] 0.702 secs with sub and data: lalalalala [11:52:42] 0.71799999999996 secs with sub and data: lalalalala [11:52:44] 0.702 secs with sub and data: lalalalala [11:52:44] 0.74900000000002 secs with sub and data: lalalalala [11:52:44] 0.73299999999995 secs with sub and data: lalalalala
Как видите на милионе операций разница есть, незначительная, так что лучше использовать?
Автор: Setuper 10.8.2009, 11:24
Быстродействие практически одинаковое. Использование match должно быть по идее эффективнее прежде всего из-за того, что вызывается всего 1 функция. Подобного рода тесты не могут точно определить быстроту выполнения, так как довольно большая погрешность вносится побочными процессами. Поэтому подобное сравнение ни о чём не говорит.
Автор: red_neon 16.10.2009, 23:47
Ещё стоит добавить, что луа не поддерживает PCRE/PREG т.е. регэкспа типа "^.+(%.mp[1-3]$|%.wav$|%.flac$)" работать не будет.
Автор: Setuper 16.10.2009, 23:51
Действительно, lua использует урезанную версию регулярных выражений. Однако, предложенное регулярное выражение может быть преобразовано и будет работать))
Автор: Кто-то_из_вне... 28.10.2009, 15:43
м...много материала , но в целом все доступно и понятно
Автор: dimajak 19.11.2010, 2:45
как понять это?
Цитата
"/(.-)/" - захват всего, что находится между ПЕРВЫМИ ДВУМЯ символами /
трудности перевода? Или как-то иначе? Первые два символа "/" - это "//" в начале строки. Что может быть между ними?
Автор: Setuper 19.11.2010, 9:54
Не говорится же, что эти символы обязательно следуют друг за другом. Если бы имелись ввиду первый два символа строки, то так и было бы написано: "первые два символа СТРОКИ", а тут написано "ПЕРВЫМИ ДВУМЯ символами /", и про расположение этих символов в строке ничего не сказано.
Символов в строке может быть больше двух. Мы получаем всё то, что находится между первыми двумя символами /.
Код
"qwerty/12345/6789/00000///123" -> "12345"
Автор: Ksan 19.11.2010, 11:56
Setuper, это относится ТОЛЬКО к символу слэш '/' ? Для всего остального (захват МЕЖДУ символами):
Цитата
%bxy
?
Автор: Setuper 19.11.2010, 12:16
Можно и то и другое использовать, только в случае %bxy захватываются ещё и концы x и y. То есть %b// захватить всё между первыми двумя символами /, включая и сами символы.
Вообще говоря примеры:
Цитата
"/(.*)/" - захват всего, что находится между КРАЙНИМИ символами / "/(.-)/" - захват всего, что находится между ПЕРВЫМИ ДВУМЯ символами /
были написаны для того, чтобы показать разницу между регулярными выражениями .* и .- , а не для того чтобы как-то обыграть слеш
Автор: Ksan 19.11.2010, 13:01
Кстати, а разницу-то я между '*' и '-' так и не понял из объяснения..
Автор: Setuper 19.11.2010, 13:26
Может на реальном примере поймёшь, раз на словах не понимаешь:
Код
local s = "123/456/789/0" print(s:match"/(.*)/") --> "456/789" print(s:match"/(.-)/") --> "456"
Автор: dimajak 20.11.2010, 3:06
Setuper, теперь ясно, спасибо. Дополните первое сообщение приведенными примерами.
Хочу сделать приватные сообщения в общем чате, т.е. обрабатывать сообщения вида "user1, user2,user3: Текст сообщения" "user1: Текст сообщения" "user1, user2, user3: Текст сообщения " и т.д. и отправлять их юзеру либо юзерам перечисленным до ":". Пока моих знаний хватило на это:
Далее nicks парсится и проверяется на ники юзеров. Если какое-либо слово из nicks не является ником юзера, то не происходит отправки сообщения указанным юзерам. (nicks - строка из одного, либо нескольких слов, разделенных ",", может быть наличие пробелов между словами и знаками). "%b<>%s+(.*):%s*(.*)" - этого достаточно? Важно учесть смайлики и правила русского языка в применении знака ":", т.е. после него мб перечисление и пр., т.е. попросту проверить на наличие ников в части до символа ":", но это проверяется потом парсингом nicks на наличие ников, главное чтобы захватить строку до первого ":".
Автор: Ksan 20.11.2010, 6:40
Попробуй вот этот корявый код:
Код
local tShadowChatNicks = { -- эти ники могут писать мультиадресные сообщения ["Indy"] = 1, ["Ksan"] = 1, ["Атыктотакой"] = 1, } local tTable = {}
function ChatArrival(tUser, sData) local sData = string.sub(sData, 1, -2) local sMsg = sData:match("^%b<>%s+(%S.*)") if sMsg and sMsg:find":" then if tShadowChatNicks[tUser.sNick] then local sNicks, sShadowMsg = sMsg:match"^(.*):%s*(.*)" sNicks = sNicks:gsub(",","") while sNicks do sWord = sNicks:match"^(%S+)" table.insert(tTable, sWord) sNicks = sNicks:gsub(sWord, "") sNicks = sNicks:match"^%s+(.*)" end for i = 1, #tTable do Core.SendToNick(tTable[i], "<"..tUser.sNick.."> "..sShadowMsg) -- тут сообщение отправляется очередному нику end Core.SendToNick(tUser.sNick, sData) -- а это идёт себе же для контроля tTable = {} -- обнуляем таблицу, готовя к след. сообщению collectgarbage() return true end end end
Просто я не знаю, как красивее выцепить (распарсить, как ты говоришь) отдельные слова неизвестного количества из сообщения, потому пришлось заниматься выкорчёвыванием пробелов и запятых...одновременно каждое очередное полученное слово заносил в таблицу, оттуда уже легко вытаскивать и делать что хочешь.
Добавил ещё сверку ника автора сообщения со списком имеющих право на такие сообщения.
P.S.: Можно еще сделать так, чтоб каждому адресату при этом сообщалось, кому ещё это сообщение отправлено. P.P.S: Только нужно помнить, что это сообщение отправится на запись в чат-лог, поэтому скрипт нужно поставить выше Чат-лога.
Автор: dimajak 24.11.2010, 23:51
Ksan, несколько иначе "выковыривал" ники, а так почти 1 в 1 пришлось добавить аналог PHP-функций http://mydc.ru/r/?http://www.php.su/functions/?explode и http://mydc.ru/r/?http://www.php.su/functions/?trim.
Хотелось бы, конечно увидеть мнение гуру Setuper.
P.S.
Цитата(Ksan @ 20.11.2010, 6:40)
Core.SendToNick(tUser.sNick, sData) -- а это идёт себе же для контроля
сильное замечание - я почти сутки дебажил код чтобы увидеть то что отправил
Автор: Setuper 25.11.2010, 11:45
Цитата
"%b<>%s+(.*):%s*(.*)" - этого достаточно? Важно учесть смайлики и правила русского языка в применении знака ":", т.е. после него мб перечисление и пр., т.е. попросту проверить на наличие ников в части до символа ":", но это проверяется потом парсингом nicks на наличие ников, главное чтобы захватить строку до первого ":".
Для кого я писал различия между ' * ' и ' - ' ?
Код
function ChatArrival(user, sData) local nicks, msg = sData:match"%b<>%s+(.-)%s*:%s*(.*)" ...
Автор: Sekretchik 7.1.2011, 1:04
Доброго вам всем времени суток. Подскажите пожалуйста мне такой момент. Пытаюсь сделать захват строки MyINFO. Но получается 5 переменных
соответственно, захват из моего примера берёт: $MyINFO $ALL (%S+)%s+ равно $MyINFO $ALL [Ник]+пробел ([^$]*)$ равно [Описание][Тэг]$ - одной строкой до знака - $ $([^$]*)$([^$]*)$([^$]+) равно $[Соедиенние][Флаг] - одной строкой до знака - $ затем $[E-Mail]$[Шара]$|
Подскажите, как лучше сделать захват по всем значениям MyINFO - что бы захватило все значения в 7 переменных.
Спасибо Вам Илья. Я учусь и набираю опыт с вашей помощью. Но у меня вопрос. в переменную sDesc записывается [Описание][Тэг]. Я хотел бы разделить их на две разные переменные. Это возможно?
Автор: Setuper 7.1.2011, 12:21
Код
local sDescription, sTag = sDesc:match'^(.*)(<.*>)$' if not sDescription then sDescription = sDesc sTag = '' end
Автор: Serx 9.1.2011, 3:12
ещё бы описание того что делают в регулярных выражениях квадратные скобки... Насколько я понимаю в них указываются варианты символов, которые могут быть в этом месте строки, а как быть если эти варианты состоят не из одного символа? Аналогично и для "всяких плюсиков" т.е. возможно ли использовать их относительно группы символов и если да, то как её обозначить?
Автор: Setuper 9.1.2011, 13:58
Квадратные скобки обозначают так называемые символьные класса. Это означает, что на данном месте может стоять любой из символом, который указан в символьном классе. В символьном классе возможно задать диапазоны символов: [А-Яа-я]. Так выглядит диапазон всех русских букв за исключением Ё и ё. Что касается плюсика, то к символьному классу можно его применять.
Код
local s="baaabbbababbbaaaaab bababbbababbabbabbab" print(s:match"([ab]+)") -- Результат: baaabbbababbbaaaaab
Автор: Nickolya 9.1.2011, 15:45
Цитата(Serx @ 9.1.2011, 3:12)
а как быть если эти варианты состоят не из одного символа?
В луа, к сожалению, в регулярках подобного нету, так что приходится делать несколько выражений.
Автор: Ksan 9.1.2011, 16:41
Цитата
а как быть если эти варианты состоят не из одного символа?
Serx, пример приведи..
Автор: Serx 9.1.2011, 17:48
Nickolya уже ответил, то что я и думал (как бы мне этого и не хотелось)
Ksan: я просто сейчас составляю выражения для антимата (не захотел брать готовый "набор выражений", чтобы самому получше разобраться) и вот сейчас чтобы без мата пишу пример который первый пришел в голову: допустим хочется перехватить "ложку" и "ложечку" не затрагивая слова "ложе" у меня были мысли чтобы записать выражение вроде
Код
ло[(ж)(жеч)]ка
как я понял такое в LUA одним выражением не осуществить)
Автор: Ksan 9.1.2011, 18:00
1. Может, поможет это:
Код
"лож[е]?[ч]?ка"
Вряд ли напишут "ложчка" или "ложека" Ну я проверил, работает (а как же иначе?) Вот результат в чате:
2. Ну либо "ложе" вводи в исключения. А насчёт "ложчка" - лично у себя я опечатки и орфографические ошибки не ввожу в исключения, пусть учатся грамотно писать.
Автор: Setuper 9.1.2011, 18:11
Дело в том, что в регулярке lua, в отличие от перловской регулярки, нету знака "или", который обозначается в перле пайпом - "|".
Что касается указанного примера:
Код
"лож[е]?[ч]?ка"
то тут можно обойтись и без символьных классов:
Код
"ложе?ч?ка"
Автор: Ksan 9.1.2011, 18:16
Не подумал. Но по большому счёту там могли быть и 2 и больше символов, просто это пример такой простой.
Автор: MIKHAIL 8.12.2011, 1:03
Подскажите, пожалуйста, как организовать захват всего http://mydc.ru/r/?http://pogoda.by/rss2/cityrss.php?q=26850, что удовлетворяет условию:
Код
..:match("<pubDate>(.-)</pubDate>")
При таком шаблоне у меня, естественно, только одно совпадение и, соответственно, один захват. Что надо дописать в шаблон, чтобы происходил захват всех таких совпадений? Логика подсказывает, что нужен плюс "+", только вот куда его вставить?
Автор: Ksan 8.12.2011, 2:51
Попробуй внедрить в свой скрипт эту процедуру (названия переменных можешь изменить как тебе понравится):
Код
t = {} for k, v in sMsg:gmatch("<pubDate>.-</pubDate>") do local s = v:match("<pubDate>(.-)</pubDate>") t[k] = s end
При выполнении все строки, содержащее нужную тебе информацию (в данном случае время/дату) сохранятся в таблицу t Потом сможешь вытаскивать их когда и как тебе угодно, например, так:
Код
local sTime = t[1]
дальше это вставляешь в своё выводимое сообщение в нужное место.
Автор: Alexey 8.12.2011, 2:54
Используй конструкцию типа:
Код
for v in sData:gmatch"<pubDate>(.*)</pubDate>" do ... end
Внутри этого цикла переменной v будет поочерёдно присвоено значение из всех захватов по маске.
PS: Страницу с погодой я не смотрел и потому правильность маски не гарантирую. PPS: Ну Ksan!!! Опередил... :P
Автор: Xomut 23.1.2012, 10:01
Здавствуйте) Подскажите а какой символ в регулярных выражения lua используется для отступов(табуляции)??? в каждой строке есть несколько отступов, нужно найти содержимое между ними, ниче не могу придумать(((
Автор: Артём 23.1.2012, 11:50
Xomut
Код
%s - \t \n \v \f \r <space>
Автор: Setuper 23.1.2012, 16:42
можно заюзать "\t+(%S*)"
Автор: MIKHAIL 4.3.2012, 2:08
Захват с начала строки понятен. Но как организовать захват с конца строки до ближайшего символа "/" влево в случае, если строка по длине непостоянна и количество директорий может меняться. Например, захватить имя файла (может меняться) с расширением (может меняться) – "sFileName.sExt":
Поиск/захват строки всегда идёт только слева направо, т.е. с начала строки и до конца, или есть вариант наоборот – справа налево, т.е. с конца строки и до начала без каких-либо лишних сортировок?
Автор: Enyby 4.3.2012, 3:01
Слева направо. Но тебе никто не мешает сделать реверс строки (string.reverse), а потом гонять регулярки. К найденным кусками потом снова применить реверс и будет поиск справа налево.
Автор: Ksan 4.3.2012, 3:56
MIKHAIL:
Код
local sFilePath = "http://sHostName/sDir1/sDir2/sDir3/sDirN/sFileName.sExt" local sFileName = sFilePath:gsub(".-/", "")
Автор: MIKHAIL 4.3.2012, 12:23
Ksan, наверное, имел в виду:
Код
local sFileName = sFilePath:gsub(".*/", "")
Автор: Setuper 4.3.2012, 13:16
Реверс делать не эффективно. Эффективнее ограничиться правильной регуляркой. Замена gsub тоже не эффективный вариант, так как заменять каждый символ затратно.
Вариант 1:
Код
local sFileName = sFilePath:match".+/(.*)$"
Вариант 2:
Код
local sFileName = sFilePath:match"[^/]*$"
В случае если после последнего слеша ничего нету, то в обоих вариантех получим пустую строку. В случае если слешей вообще нету, то в первом варианте получим nil, во втором варианте получим всю строку.
Какой вариант лучше - решать самому скриптописателю.
Автор: Ksan 4.3.2012, 21:21
Setuper, я имел в виду именно то, что написал. Перед написанием сюда я проверил у себя. Но если настаиваешь на "*" вместо "-", то было бы проще сразу написать, почему (именно для данного случая), потому что правильный ответ выдаёт и так и иначе. При любых видоизменениях исходного текста пути.
Автор: GULAM33 5.10.2012, 8:15
У меня деликатный вопрос по поводу регулярных выражений. Функция sData = string.gsub скрипт анти-мат. Например, надо поймать матерное слово [X][Y][Z] sData = string.gsub(sData, "[X][Y][Z]", Но [X][Y][Z] - является продолжением допустимого слова [a][b][c][d]-[X][Y][Z]. А так же [X][Y][Z] является началом другого допустимого слова [X][Y][Z]-[a][b][c][d]. И ещё [X][Y][Z] является внутренней частью (корень, суффикс) слова [a][b][c][d]-[X][Y][Z]-[a][b][c][d]
sData = string.gsub(sData, "%s[бX][лY][яZ]%s", replWord) , где replWord - замена мата на безобидное слово, %s - пробельный символ. Исключения: <оскор_бля_ть>, <о_бля_пать> и так далее.
-При детектировании необходимо опускать допустимые слова, то что у меня получилось введение пробела %s
Необходимо фиксировать слово когда юзер пишет в чат сразу после своего nick'a [X][Y][Z], без пробела на конце. Выводится в чат, если вводить просто запрещенное слово без пробела между ником и словом и без пробела после слова: 01:20:03 <NICK> XYZ
Как исправить эту ситуацию, какое регулярное выражение необходимо применить?
Автор: Setuper 5.10.2012, 9:23
Код
"%sXYZ$"
Если скрипт для PtokaX, то предварительно нужно удалить символ | с конца строки, или же писать так:
Код
"%sXYZ|$"
Автор: GULAM33 5.10.2012, 16:20
Спасибо, я подозревал о наличии "невидимого пробела" .
Автор: GULAM33 10.10.2012, 1:15
Выяснил следующее. Одного вида захвата будет не достаточно. Так как захват "%sСЛОВО|$" будет работать в случае, если после СЛОВА не будет пробела. А так выводит в чат Поэтому необходимо СЛОВО захватить двумя разными захватами чтобы запрещённые слова не выводились в чат: "%sСЛОВО|$" и "%sСЛОВО%s".
Автор: GULAM33 13.10.2012, 2:06
Данный символ " является инструментом для захвата. Является ли символ магическим. Как экранировать данный символ? Пример экранирования любого магического символа мне не помог. (%.) и (%") .
Автор: Saymon21 13.10.2012, 2:21
Цитата
Как экранировать данный символ?
Код
string = "\"Hello world\""
Тоже самое будет и для одинарных ковычек.
Автор: GULAM33 14.10.2012, 1:12
А захват данного символа как осуществить?
Автор: Setuper 15.10.2012, 9:06
\" - это Lua экранирование, так как кавычка является символом синтаксиса Lua (в отличие от символа %, который является экранирующим символом в регулярном выражении). Захватить символ можно скобками:
Код
str:find"(\")"
можно написать так:
Код
str:find'(")'
То есть, экранировать кавычки нужно в том случае, когда эти же кавычки обозначают строку.
Автор: GULAM33 22.10.2012, 10:34
Огромное спасибо Setuperу, помогли разобраться .
Автор: MIKHAIL 12.8.2014, 22:17
Что за %с – контрольный символ? Пожалуйста, приведите пример.
Автор: Ksan 13.8.2014, 0:39
MIKHAIL, Подозреваю, это непечатаемые символы с цифровым кодом до 32 (от 0 до 31). Как пример - \r, \n, \t Надеюсь, они вам знакомы? Вот полный перечень этих символов: %c: \0 \1 \2 \3 \4 \5 \6 \a \b \t \n \v \f \r \14 \15 \16 \17 \18 \19 \20 \21 \22 \23 \24 \25 \26 \27 \28 \29 \30 \31 Возможно, есть ещё один символ. Где-то на форуме было описание каждого из них.
Автор: Alexey 13.8.2014, 1:27
Неправильный перевод. Это http://mydc.ru/r/?https://ru.wikipedia.org/wiki/%D0%A3%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D1%8F%D1%8E%D1%89%D0%B8%D0%B5_%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D1%8B. Для ответов на подобные вопросы даже http://mydc.ru/topic3417.html выложили.