java.lang.StackOverflowError на Regexp
От: hl-man  
Дата: 16.05.13 16:41
Оценка:
Всем привет!

Есть такое РВ:
^(%[\\dA-F]{2}|[\\w\\-.~!$&'()*+,;=])*$

Оно используется для проверки правильности части hostname в URL.
Для более быстрого понимания объясню его суть: любое количество сочетаний закодированных символов (например %AA) или любого одиночного символа из множества -.~!$&'()*+,;= , включая "слвесные" символы. По-скольку теоретически в URL могут встречаться как закодированные так и незакодированные символы, то используется "альтернация" посредством |.
Вот из-за нее то и происходит StackOverflowError , когда мы пытаемся проверить строку на соответствие РВ, в случаях когда длина строки превышает примерно 1500.

Вопрос в том, можно ли как-то избежать использования палки "|" в данном случае?

Ну и конечно альтернативные предложения принимаются
Re: java.lang.StackOverflowError на Regexp
От: Аноним  
Дата: 16.05.13 18:24
Оценка:
Погонял и так и сяк — ничего не выходит. Порежь на куски и проверь по отдельности.
Re[2]: java.lang.StackOverflowError на Regexp
От: Аноним  
Дата: 16.05.13 19:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Погонял и так и сяк — ничего не выходит. Порежь на куски и проверь по отдельности.


Или в 2 прохода гонять

— 1й проход замена %[\dA-F]{2} на какой-нибудь символ из второго набора, но не цифра или A-F, например !
— 2й проход — поиск уже по второму набору
Re: java.lang.StackOverflowError на Regexp
От: PAS_Tor Германия http://passtor.blogspot.com/
Дата: 16.05.13 19:27
Оценка:
Здравствуйте, hl-man, Вы писали:

HM>Вопрос в том, можно ли как-то избежать использования палки "|" в данном случае?


HM>Ну и конечно альтернативные предложения принимаются


У Вас же взаимоисключающие условия добавте жадные плюсики и наслаждайтесь:

^((%[\\dA-F]{2})+|[\\w\\-.~!$&'()*+,;=]+)*$

У меня выдерживает 22000 символов стабильно.
Follow my blog @ http://passtor.blogspot.com/
Re[2]: java.lang.StackOverflowError на Regexp
От: Аноним  
Дата: 16.05.13 20:21
Оценка:
PAS>^((%[\\dA-F]{2})+|[\\w\\-.~!$&'()*+,;=]+)*$

PAS>У меня выдерживает 22000 символов стабильно.


У меня на 2000 валидных символах + 1 невалидный в конце (например, @) повисает на больше чем на минуту, потом я его вырубаю
Re[3]: java.lang.StackOverflowError на Regexp
От: Blazkowicz Россия  
Дата: 16.05.13 20:25
Оценка:
Здравствуйте, Аноним, Вы писали:


PAS>>^((%[\\dA-F]{2})+|[\\w\\-.~!$&'()*+,;=]+)*$

PAS>>У меня выдерживает 22000 символов стабильно.
А>У меня на 2000 валидных символах + 1 невалидный в конце (например, @) повисает на больше чем на минуту, потом я его вырубаю
Не проще ли на pure Java переписать?
Re[3]: java.lang.StackOverflowError на Regexp
От: PAS_Tor Германия http://passtor.blogspot.com/
Дата: 16.05.13 20:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>У меня на 2000 валидных символах + 1 невалидный в конце (например, @) повисает на больше чем на минуту, потом я его вырубаю


У меня 22000 валидных + 1 невалидный обрабатывается 60мс без оптимизаций В любом случае можно попробовать вылечить с помощью possessive quantifiers, которые поддерживаются в Java, чтоб бектрекинг отрубить.

^((%[\\dA-F]{2})++|[\\w\\-.~!$&'()*+,;=]++)*+$
Follow my blog @ http://passtor.blogspot.com/
Re[4]: java.lang.StackOverflowError на Regexp
От: Аноним  
Дата: 16.05.13 20:32
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Аноним, Вы писали:



PAS>>>^((%[\\dA-F]{2})+|[\\w\\-.~!$&'()*+,;=]+)*$

PAS>>>У меня выдерживает 22000 символов стабильно.
А>>У меня на 2000 валидных символах + 1 невалидный в конце (например, @) повисает на больше чем на минуту, потом я его вырубаю
B>Не проще ли на pure Java переписать?

Пусть переписывает

Ещё как вариант можно обратную задачу решать — искать хоть один невалидный символ — по идее будет быстрее
Re[4]: java.lang.StackOverflowError на Regexp
От: PAS_Tor Германия http://passtor.blogspot.com/
Дата: 16.05.13 20:32
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Не проще ли на pure Java переписать?


Нет, конечно! Когда мы искали простых путей?!
Follow my blog @ http://passtor.blogspot.com/
Re[5]: java.lang.StackOverflowError на Regexp
От: Аноним  
Дата: 16.05.13 20:38
Оценка:
А>Ещё как вариант можно обратную задачу решать — искать хоть один невалидный символ — по идее будет быстрее

Например, так

[^\w\-.~!$&'()*+,;=%]|%(?![\dA-F]{2})
Re: java.lang.StackOverflowError на Regexp
От: hl-man  
Дата: 17.05.13 04:56
Оценка:
Здравствуйте, hl-man, Вы писали:

HM>Всем привет!


HM>Есть такое РВ:

HM>^(%[\\dA-F]{2}|[\\w\\-.~!$&'()*+,;=])*$

В итоге решение было таким:

^(?>%[\dA-F]{2}|[\w-.~!$&'()*+,;=])*$

Спасибо всем откликнувшимся ^_^
Re[2]: java.lang.StackOverflowError на Regexp
От: PAS_Tor Германия http://passtor.blogspot.com/
Дата: 17.05.13 09:25
Оценка:
Здравствуйте, hl-man, Вы писали:

HM>В итоге решение было таким:


HM>^(?>%[\dA-F]{2}|[\w-.~!$&'()*+,;=])*$


HM>Спасибо всем откликнувшимся ^_^


По сути ты избавился от части бектрекинга атомарными группами. Possessive quantifiers сделает тоже самое и быстрее. Кстати, если у тебя символы встречаются чаще чем %ХХ, то стоит их поменять местами в регулярке.
Follow my blog @ http://passtor.blogspot.com/
Re[3]: java.lang.StackOverflowError на Regexp
От: hl-man  
Дата: 17.05.13 09:31
Оценка:
Здравствуйте, PAS_Tor, Вы писали:
PAS>Possessive quantifiers сделает тоже самое и быстрее.
Гм... Возможно. По правде говоря я не очено то в них "въехал", потому и задействовал атомарные группы Надо изучить вопрос.
PAS>Кстати, если у тебя символы встречаются чаще чем %ХХ, то стоит их поменять местами в регулярке.
Тоже учту. Спасибо за совет.
Re[4]: java.lang.StackOverflowError на Regexp
От: PAS_Tor Германия http://passtor.blogspot.com/
Дата: 17.05.13 10:30
Оценка: 3 (1)
Здравствуйте, hl-man, Вы писали:

PAS>>Possessive quantifiers сделает тоже самое и быстрее.

HM>Гм... Возможно. По правде говоря я не очено то в них "въехал", потому и задействовал атомарные группы Надо изучить вопрос.

Расчёт на то, что если ты встретил незакодированный символ, то с очень большой вероятностью следующий символ тоже будет не закодирован. То же самое с "процентными" группами. Так что имеет смысл выбирать сначала повторения, без необходимости обращаться к |.

Есть три нотации повторений:

Жадные – .+ – сначала отбирают всё что могут, потом, если нужно, потихоньку отдают символы строке назад (бектрекинг)
 

Ленивые – .+? – стараются как можно быстрее перескочить на последующую часть RegExp


Притяжательные (Possessive quantifiers) – .++ – работает как жадный алгоритм, но не сохраняет инфо для бектрекинга.
Follow my blog @ http://passtor.blogspot.com/
Re[5]: java.lang.StackOverflowError на Regexp
От: hl-man  
Дата: 17.05.13 10:58
Оценка:
Здравствуйте, PAS_Tor, Вы писали:

PAS>Есть три нотации повторений:


PAS_Tor, благодарю за подробнейшие разъяснения! Это было очень полезно
Re: java.lang.StackOverflowError на Regexp
От: . Великобритания  
Дата: 19.05.13 12:41
Оценка:
Здравствуйте, hl-man, Вы писали:

h> Ну и конечно альтернативные предложения принимаются

А java.lang.URL принимается?
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.