Регулярные выражения

Russian main discussion
  • Author
  • Message
Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Serge Yolkin
не помогло. Да это и не спец-символы, чтобы их экранировать.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Разобрался: оказалось, что правила всё-таки конфликтуют друг с другом (и теперь предстоит разобраться каким именно образом они конфликтуют).
правило

Code: Select all

0	"^\s*+([^\s,`]+)\s*+:" `\1=(4,${TAG},0)`
перебивало то правило (хотя то правило и находилось в списке выше) на такой строке
var := value
Изменил это правило на более полное

Code: Select all

0	"^\s*+([^\s,`]+)\s*+:\s*+((?<=\s);.*)?$" `\1=(4,${TAG},0) \2=(3,${COMM},0)`
и всё стало ок.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Ещё странное:

Code: Select all

0	`^(?:(Global)\s++)?+([\w#@\$\.]+?)$` `\1=(0,${TYPE},0) \2=(0,${VAR},0)`
раскрашивает строки вот так:
Image
хотя в третьей строке слово global должно раскрашиваться как ${VAR}, а не как ${TYPE}, ведь после условия (Global) идёт \s++, т.е. явное указание на необходимость наличия хотя бы одного пробельного символа после "global", чтобы тот стал подсвечиваться как ${TYPE}.
Это уже точно баг.

Если правило изменить на

Code: Select all

0	`^(Global\s++)?+([\w#@\$\.]+?)$` `\1=(0,${TYPE},0) \2=(0,${VAR},0)`
то всё начинает подсвечиваться как надо, но ведь в таком случае пробелы после global будут захватываться, а значит если я назначу 1-ой суб-группе цветной фон, то и все те пробелы будут иметь цветной фон.

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Drugmix wrote:Positive lookbehind'ы поломались?
AkelHelp-Rus.htm wrote:(?<=шаблон) Положительный просмотр назад (positive lookbehind). Соответствие не сохраняется для последующего использования. Например, '(?<=abc)z' соответствует "z" только, если ему предшествует "abc". Шаблон должен быть фиксированной длины.
Drugmix wrote:Image
При проверке "StringyLauncher.ahk" столкнулся с подобным поведением. См. тестовую.
...раскрашивает строки вот так...
Тестовая

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Instructor
:o Ураааа! :D
баг с переокрашиванием стал проявляться раз в 100 реже (на ahk-скриптах исправлен совсем), акелпадом снова можно пользоваться!!

Если хочется добить баг насовсем, то можно потренироваться на строках секции QuotesRE моего текущего ahk.coder с применённым этим coder.coder.
Баг особенно заметен при прокрутке не колесом мыши или клавишами клавиатуры, а тасканием кнопки прокрутки на скроллбаре.

Offline
Posts: 366
Joined: Mon Jan 10, 2011 5:28 pm
Contact:

Post by Lenchik »

У меня он как раз более заметен при хождении курсора клавишами. Прям блоками цветам меняются. А свернуть и развернуть акель - вообще другие - наверное задуманные цвета, но до следующей прокрутки. А скролл ползунком, наверное, у нас по-разному на отрисовку настроен.

Image

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Lenchik
Да, это я погорячился с описанием: чаще неверная окраска происходит как раз при скролле колесом или клавиатурой.
А с прокруткой за ползунок на скролл-баре баг интересно (хоть какая-то логика у него есть) воспроизводится: если мышью этот ползунок вручную таскать по скроллбару, то вроде как хаотично возникает баг, а вот стоит сделать клик по скроллбару над или под ползунком, чтобы прокрутилось всё на 1 экран вниз или вверх - как тут же становится всё верно окрашено, кроме самых верхних строчек: если включена настройка Wrap words (ctrl+U), то длинные строки переносятся на несколько строк и если начало длинной строки осталось вверху за границами видимой области, то те обрезки этой длинной строки, которые находятся в рамках видимой области - окрашиваются неверно.

Image

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Drugmix wrote:Если хочется добить баг насовсем...
Здесь уже проблема в пересечении правил. Закомментируйте секцию "Quotes:" и наложений не будет. Помним, что у секции "Quotes:" больший приоритет, чем у "QuotesRE:".

Правило в QuotesRE можно записать одно вместо 9-ти:

Code: Select all

QuotesRE:
;=========================================================================
;Flags  Pattern        \BackRef=(FontStyle,ColorText,ColorBk) \BackRef=...
;=========================================================================
0	"^(\d++)\s++([\x22'`])(.*?)(\2)\s++([\x22'`])(.*?)(\5)"	"\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)"
;
; Highlight rules for QuotesRE: section.
;0	'^(\d++)\s++(")(.*)(")\s++(")(.*)(")'	'\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)'
;0	'^(\d++)\s++(")(.*)(")\s++(`)(.*)(`)'	`\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)`
;0	'^(\d++)\s++(`)(.*)(`)\s++(")(.*)(")'	"\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)"
;0	`^(\d++)\s++(')(.*)(')\s++(')(.*)(')`	`\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)`
;0	`^(\d++)\s++(')(.*)(')\s++(")(.*)(")`	'\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)'
;0	`^(\d++)\s++(")(.*)(")\s++(')(.*)(')`	"\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)"
;0	"^(\d++)\s++(`)(.*)(`)\s++(`)(.*)(`)"	'\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)'
;0	"^(\d++)\s++(`)(.*)(`)\s++(')(.*)(')"	`\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)`
;0	"^(\d++)\s++(')(.*)(')\s++(`)(.*)(`)"	"\1=(0,${NUM},0) \2=(0,${VAR},0) \3=(0,${OP},0) \4=(0,${VAR},0) \5=(0,${VAR},0) \6=(0,${ATTR},0) \7=(0,${VAR},0)"

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Instructor
гм. Занятно. Не знал, что Quotes перебивают QuotesRE и не знал, что можно в шаблонах правил QuotesRE использовать backreference'ы.
Пора бы мануал начать делать :)

YuS
Offline
Posts: 512
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

DV wrote: Смысл "хака" в том, что выражения вида .* и .+ до сих пор остаются "сверхжадными", выделяя весь файл до конца,
Хмм, а тесты говорят о другом...
Вот такой, например, текст:

Code: Select all

abcdef
ghijkl
mnopqrst
mnopqrst
шаблон:

Code: Select all

^.*no
также как и

Code: Select all

^.+no
выбирает совпадение до крайнего "no" в последней строке, включая само "no", т.е. наибольшее возможное совпадение.
Такое поведение говорит о жадности квантификатора "*" и "+", в том числе и со спецсимволом "." .
При сверхжадном же квантификаторе ".*+" совпадения не будет найдено, т.к. текст будет захвачен полностью, до самого последнего символа и для "no" совпадения уже не будет.
При ленивом же квантификаторе ".*?" будет захвачен текст до первого "no" включительно, что соответствует наименьшему совпадению шаблона.
Итого: квантификаторы работают классически, без исключений, о чем, кстати, есть запись в "AkelHelp-Rus.htm".
При жадном квантификаторе происходит перебор возможных совпадений, а при ревнивом квантификаторе происходит захват максимально возможного варианта и без всяких дальнейших переборов, что, по сути, должно быть значительно быстрее при выполнении кода...

Offline
Posts: 294
Joined: Tue Jul 27, 2010 11:18 pm

Post by Serge Yolkin »

YuS
Насколько я понял, хак убирает квантификатор, только если он в самом конце выражения, если после него что-то есть ("no"), то ничего не хачится.

YuS
Offline
Posts: 512
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

Serge Yolkin wrote:YuS
Насколько я понял, хак убирает квантификатор, только если он в самом конце выражения, если после него что-то есть ("no"), то ничего не хачится.
Не-не-не, я о самом хаке ничего не говорил, только лишь уточнил, что текущая жадность квантификаторов соответствует классическим, причем без исключений.
Дело в том, что в предыдущих версиях AP, в описании было вот такое замечание-исключение:

Code: Select all

- Квантификаторы регулярных выражений (*, +, {n,}) являются по умолчанию жадными (кроме одинарной точки, например, ".*" или ".{5,10}").
Чего в текущей реализации AP уже нет.

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Skif_off wrote:Вертикальной прокруткой прокрутил файл вниз-вверх и AkelPad завис...
Drugmix wrote:Если хочется побороться с падениями, то вот, например, правило под старый парсер:

Code: Select all

0	`"((?:[^"]*?(?:"")?)*?)"` `\1=(0,${STR},0)`
которое способно сейчас положить акелпад на файле с длинными строками, содержащими множественные кавычки, например на этом, если его быстро поскроллить туда-сюда.
Тестовая

DV
Offline
Posts: 1250
Joined: Thu Nov 16, 2006 11:53 am
Location: Kyiv, Ukraine

Post by DV »

По поводу использования +, *, +? и *? в конце регулярного выражения.
Пусть у нас есть следующий текст:

Code: Select all

abc     def     
ghi     jkl     
Если поместить каретку в начало текста, то поиск с применением следующих регулярных выражений из стандарного диалога поиска:

Code: Select all

abc.*
abc.+
abc.*?
abc.+?
abc[^x]*
abc[^x]+
abc[^x]*?
abc[^x]+?
выделяет весь текст до конца файла!
По моему скромному мнению, вариант +? или хотя бы *? не должен быть таким жадным!
Ведь регулярка abc.*? в качестве минимального вхождения должна бы сработать на текст "abc", не "заглатывая" весь оставшийся текст.
Точно так же abc.+? мог бы удовлетвориться текстом "abc " (с одним пробелом в конце) - но нет же, он "заглатывает" всё!

YuS
Offline
Posts: 512
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

DV wrote: Ведь регулярка abc.*? в качестве минимального вхождения должна бы сработать на текст "abc", не "заглатывая" весь оставшийся текст.
Точно так же abc.+? мог бы удовлетвориться текстом "abc " (с одним пробелом в конце) - но нет же, он "заглатывает" всё!
Гмм, по-моему, тут всё верно. Давайте читать регэксп буквально, как это рекомендуют во многих источниках...
Разберем пример с ленивым квантификатором:

Code: Select all

abc     def      
ghi     jkl
1. abc.*? - совпадает:
а) если сразу за символом "a" следует символ "b",
б) если сразу за символом "b" следует символ "c"
в) если сразу за символом "c" следует любой символ ноль или более раз
Причем ленивость квантификатора не означает, что он произвольно будет выделять всего один символ вместо неопределенного количества, тут должно быть какое-либо ограничение, следующее за ленивым квантификатором, а его, как раз и нет. И да, если совпадений по ограничению будет несколько, то будет выбран наименьший возможный вариант, а для рассматриваемого примера, наименьший возможный вариант совпадения - весь текст до конца.
Post Reply