В большинстве языков программирования существуют
примитивные средства поиска по шаблону (обычно в виде дополнительных библиотек), но шаблоны Perl интегрированы на уровне самого языка. Они обладают возможностями, которыми не владеют другие языки; возможностями, которые позволяют взглянуть на данные с новой точки зрения.
1. Поиск.
Вообще говоря, поиск - основная часть программирования. На его основе работают сотни алгоритмов: от простых до сложных. Если время поиска минимальное - производительность программы будет
максимальной и наоборот, поэтому для тебя важно выбрать нужное решение в определенной ситуации.
Как ты знаешь, поиск легче всего выполнить через регулярные выражения. Самым примитивным шаблоном является regexp, состоящий из единственной подстроки, вида:
$string=~m/word/;
или
$string=~/word/;
Как ты понимаешь, эта конструкция истина в том случае, если значение переменной $string содержит слово "word".
Это самое простое, что может быть в Perl. Далее переходим к более сложным вещам.
Допустим, тебе необходимо выделить из произвольной строки отдельные слова. За символ пробела у нас отвечает символ \S. Следовательно, при его инверсии мы добьемся цели. Итак, regexpы
$words=~/\S+/;
или
$words=~/([A-Za-z'-]+)/;
позволят нам достигнуть результата.
Можно выделить границы слов идентификатором \b. Тогда регвыр принимает иной вид:
$words=~/\b([A-Za-z]+)\b/;
Для справки, все отобранные слова будут занесены в переменную $1 (которая выделяется скобками).
Другая актуальная проблема - нам нужно найти повторяющиеся слова в тексте. Сделать это нам помогут обратные ссылки в регулярных выражениях. После поиска чего-либо, формируются шаблоны-идентификаторы вида \1, \2 и т.д. Они несут в себе первое, второе и т.д. совпадения. С помощью них можно добиться поставленной задачи и обнаружить в тексте повторяющиеся слова. Перед фрагментом кода, напомню, что модификатор /i в regexp отвечает за чувствительность к регистру (при его наличии - регистр не учитывается), а /g ведет поиск до конца текста. Про метасимволы \b и \s я уже упоминал (граница слова и символ пробела).
$/=''; ## Переопределяем конец слова с \n на пустоту (сливаем строку)
while(<>) {
while( m{ ## Начинаем регвыр
\b # Находим границу слова
(\S+) # Берем все, что после границы
\b # И до следующей границы
(
\s+ # Игнорим все пробелы
\1 # И проверяем на наличие первого слова
\b # До его границы
) + ## И так далее
}xig ## x позволяет разделять и комментировать регвыры
)
{ print "Найдено совпадение $1 в абзаце $.\n"; ## Выводим отчет по каждому совпадению }
}
Такой программой мы находим повторяющиеся слова. Знаю, понять регвыры не так то просто, нередко приходится смотреть на шаблоны по полчаса, чтобы разобрать их. Но польза от regexp огромна. Одно выражение позволяет заменить десятки строк кода.
Хочется сказать о поиске в массивах. Меня очень часто спрашивают
- как найти элементы одного массива, которые отсутствуют в другом. На самом деле все просто. Нужно лишь вспомнить такое понятие, как хэш. С
его помощью можно добиться результата. Имеем два массива @yes и @no. По @yes производим поиск, который должен
удовлетворять условию - отсутствию этих элементов в @no.
%hash = (); ## Хеш для проверки
@ok = (); ## Массив удовлетворяющих элементов
foreach $elem (@no) { $hash{$elem} = 1 } ## Строим таблицу просмотра
foreach $elem (@yes) {
unless $elem (@yes) {
## Отсутствует в %hash, поэтому добавим в @ok
push(@ok,$elem);
}
}
В итоге мы получаем массив @ok, который удовлетворяет критерию поиска.
2. Сортировка.
Сортировка - упорядочивание элементов массива по какому-либо критерию. Как правило, по возрастанию или убыванию.
Чтобы отсортировать массив по возрастанию, воспользуемся функцией Perl под названием sort. Просто добавим ее в цикл foreach таким образом:
foreach $sort (sort @unsorted) { }
Часто приходится работать с большими файлами, либо записями, которые в массив попросту не помещаются (из-за нехватки памяти). Эту проблему можно решить системным бинарником /bin/sort, который имеет некоторые полезные ключи:
-u - поиск уникальных слов и последующее их удаление из файла
-o - файл, куда будет записан отсортированный отчет.
-f - игнор регистра в словах
-r - отсортировать реверсивно (по убыванию)
Поместить внешний вызов можно в функцию system(). Таким образом, чтобы отсортировать файл по убыванию с игнором повторяющихся символов, нужно выполнить команду:
system("/bin/sort -u -r ./file -o ./sortfile");
В остальных случаях, можно ограничиться внутренней функцией sort. Как загрузить все строки из файла в отдельный массив ты уже должен знать - это не раз описывалось на страницах этого сайта.
Вопросы? Шли мылом, постараюсь помочь!