На получившемся примере кода хотел бы продемонстрировать, как при помощи пары строк с использованием регулярных выражений, можно выполнить быстрый и эффективный поиск.
Реализация
Для начала преобразуем переданные функции подсказки в часть будущего регулярного выражения:
$hints =~ s/(.)/$1\.\*\?/g;Здесь $hints — строка, склеенная из всех подсказок, например, 'abcd'.
Выражение для поиска (.) — это одиночный символ (каждый, учитывая параметр поиска 'g'), заменяем его на себя же ($1 — значение из первых скобок выражения поиска) и дописываем необходимые нам части, а именно:
После каждого символа добавляем блок: '.*?', что означает: любой символ, ноль или более раз, и маркер, который делает модификатор «не жадным» (об этом чуть ниже).
Итого на выходе получаем строку: 'a.*?b.*?c.*?d.*?'
Переходим к основной части, которая осуществляет сравнение строки из «знакомых» папок с подсказкой, условие:
if ($path =~ /^(.*)($hints)$/)Здесь символ '^' — это «якорь» начала строки, выражение в первых скобках '(.*)' — префикс строки, а вслед за этим выражением — наш подготовленный заранее regexp, содержащий подсказки для поиска, заканчивается выражение вторым «якорем» — '$', который означает совпадение с концом строки.
Поскольку все модификаторы '*' в строке кроме первого, содержат маркеры '?', единственный модификатор без этого маркера становится «жадным», т.е. старается отобрать себе как можно большую часть строки.
В нашем примере, имеем на выходе преобразованную строку: /^(.*)(a.*?b.*?c.*?d.*?)$/
Фактически, поиск в этом случае осуществляется справа налево, т.е. сначала от конца строки ищем ближайший символ 'd', потом слева от него — ближайший символ 'c', затем — ближайший к нему слева символ 'b' и затем — ближайший к нему вимвол 'a', все что будет слева от найденного смвола 'a' попадет в «жадный» префикс. Положение найденного результата в строке мы определим по длине этого префикса, а именно строкой
$w = length($1); (здесь $1 получит значение из первых скобок предыдущего regexp), остальные условия (чем правее, чем лучше) за нас уже выполнил сам regexp.Остается только дописать функции LoadPaths и add и добисать обработку параметров запуска.
Полный текст скрипта:
hg clone bitbucket.org/eugenet/perlre

