Перетворення тексту за допомогою регулярних виразів.
Сьогодні: -0 -0 -0
Зараз онлайн: На сайті -10 На IRC-каналі -3
Я пишу ці статті в MS Word через те, що він (Word) перевіряє орфографію та граматику. Але він має один істотний недолік. Статті в Інтернеті публікуються у форматі HTML і, хоча MS Word і вміє конвертувати, але робить це огидно. Сторінка, яка могла б займати 3-4 кілобайти, має вагу 20-30. Найприкріше, що все можна вичистити "ручками", а зовнішній вигляд сторінки не зміниться.
Чистимо текст за допомогою давно відомого методу – регулярних виразів.
Інструментарій
Для того, щоб продовжити роботу нам потрібно:
- Delphi 7, 2005, 2006, 2007 версії. На молодших версіях має працювати, але не гарантую; - Завантажити бібліотеку для регулярних висловів із сайту http://www.regexpstudio.com/RU/TRegExpr/TRegExpr.html. Якщо точніше, то http://www.regexpstudio.com/Downloads/regexpr_RU.zip та завантажити (це опціонально) утиліту для тестування регулярних виразів http://www.regexpstudio.com/RU/RegExpStudio.html. Все це можна взяти в архіві до статті. - Ну і напій до смаку :-)
Робочий клас
Запускаємо Delphi і відразу додаємо ще один юніт (File - New - Unit). Зберігаємо проект. "Unit2" я зберігаю під назвою "ClassTextTransf.pas". "Unit1" як "Main.pas". А сам проект як "HTMLClean.dpr". Тепер з архіву вилучимо файл "Source RegExpr.pas" і скопіюємо його в папку до нашого проекту.
Повертаємося до файлу ClassTextTransf. Після рядка interface підключаємо потрібні нам файли – uses SysUtils, Classes, RegExpr;
Знаступного рядка починаємо писати заготівлю для нашого класу.
Розглянемо цей код докладніше. На початку ми створюємо екземпляр класу (тобто об'єкт), який вміє обробляти регулярні вирази. Далі передаємо саме регулярне вираз і викликаємо функцію Replace. Її параметри наступні: перший – рядок, в якому ми видалятимемо текст, другий – на який текст будемо замінювати. Оскільки ми видаляємо, то у нас це порожній рядок. Третій параметр поки що залишаємо False. Він розширює функціональність і нам поки що не потрібний. Далі записуємо отриманий текст у нашу змінну. Як складати регулярні вирази – розберемося пізніше.
Інтерфейс
Тепер пишемо інтерфейсний код – юніт main.pas. Для початку накидаємо компоненти. У мене вийшло так:

Код кнопки "Огляд" виглядає просто:
Тут поки що нічого незвичайного.
Тепер для кнопки "Обробити". Спочатку потрібно підключити наш юніт із класом. Це просто. Меню File – Use unit та вибираємо наш юніт (він там єдиний).
І пишемо обробник для кнопки:
Як видно – нічого складного. Створили об'єкт, завантажили текст та зберегли результат. Код обробки, який власне виконує основну роль, поки що опущений.
Основи синтаксису регулярних виразів
Запускаємо, обробляємо. Потім порівнюємо. Має працювати.
Тепер складніше. Потрібно видалити тег, що відкриває. Тут можуть бути різні варіанти. Але спочатку треба спробувати описати словами. У мене виходить десь так: "спочатку кутова дужка, потім текст span потім будь-які символи крім дужки, що закриває, і власне сама дужка, що закриває». На мові регулярних виразів це виглядає так:
Конструкція[^>] означає будь-який символ крім кутової дужки, що закриває. Якщо написати[abc], це буде будь-який символ a, b або c. Конструкція виду[a-z] - якась мала літера латинського алфавіту. Конструкція виду[^0-9] – всі символи, крім цифр.
Зірочка (* ) означає, що таких символів може бути 0 або більше. Якщо поставити+, це означатиме, що має бути хоча б один символ.
Якщо тепер додати ще один рядок до нашого коду, то html очищається на 25%, а це вже непогано!
Наступний хід – замінити конструкції виду.
Наш клас не вміє робити таку заміну. Але ми додамо ще один метод. Назвемо його Replace(FromText, ToText: string);
Якщо придивитися, то можна помітити, що наш попередній метод є окремим випадком цього. Erase(s) еквівалентно Replace(s,''). Тому додамо новий метод, скопіюємо туди код із методу Erase і виправимо його. Тобто у нас вийде так:
Запитайте, а в чому ж краса? А в тому, що нам не потрібно змінювати код основного юніту! Правильно спроектований клас приховує функціональність усередині та при оптимізації код, який використовує наш клас, не помітить змін. Також це зручно для розподілу праці. Потрібно лише домовитись про інтерфейс класів.
Тепер код заміни для нашого рядка буде виглядати просто:
Тут тільки одна особливість - пробіл потрібно записати у вигляді\s.
Ці рядки видалять щось не зовсім мені зрозуміле, але що заважає нормальному відображенню зображень у браузері. Найцікавіше, що вони заважають лише Internet Explorer'у. Іншим браузерам цей код – не завада.
Подивимося тепер на дивний текст після тега html у самому верху. Дуже багато там інформації. Вона потрібна, щоб у html документів, створених Word'ом, відображалася трохи інша іконка і саме Word викликався при спробіредагування. Нам це не потрібне. Тут код простий:
Тепер додамо трохи "краси". Після наших видалень залишилося багато порожніх рядків. Вилучимо їх. Для цього використовуватимемо виразReplace('\n\s*\n',''); У класі я оформив це у вигляді додаткового методу.
Після всіх маніпуляцій мені вдалося вичистити текст більш ніж у 2 рази. У ньому, звичайно, ще є місце для ручної обробки, але в цілому дуже непогано. У коді ви знайдете кілька додаткових рядків для оцінки продуктивності.
Безперечним плюсом вивчення регулярних виразів є те, що вони використовуються у багатьох інших мовах, таких як Perl, PHP. Ця бібліотека сумісна з Perl'івською реалізацією і тому літератури в Інтернеті є достатньою.
Автор: Вадим К
Статті, схожі на тематику
Щоб вставити посилання на цю статтю на іншому сайті, використовуйте наступний HTML-код:
Посилання для форумів (BBCode):