- Вступ Регулярні вирази (англ. Regular expressions) - особливий інструмент, мова для обробки текстів...
- 2. Особливості реалізації регулярних виразів для MQL5
- 2.2. Особливості бібліотеки RegularExpressions для MQL5.
- 3. Приклад розбору торгової історії
- 4. Приклад розбору результатів оптимізації експерта
- 5. Короткий опис прикладів з бібліотеки RegularExpressions для MQL5
- Висновок
- ПОСИЛАННЯ
Вступ
Регулярні вирази (англ. Regular expressions) - особливий інструмент, мова для обробки текстів за заданим зразком. Такий зразок, або патерн, має й інші назви - шаблон або маска регулярного виразу. Синтаксисом регулярних виразів визначені безліч метасимволов і правил.
Регулярні вирази здатні виконувати дві основні задачі:
- пошук шаблону в рядку;
- заміна знайденого шаблону.
При складанні шаблонів для регулярних виразів, як ми вже написали, використовуються спеціальні символи, метасимволу і класи (набори) символів. Це означає, що регулярний вираз являє собою звичайну рядок, і все неспеціальні (незарезервірованних) символи в ній вважаються звичайними.
Саме пошук заданого патерну в рядку здійснюється оброблювачем регулярних виразів. В .NET Framework, а отже - і в бібліотеці RegularExpressions для MQL5 , Обробник регулярних виразів виконує пошук з поверненням для регулярних виразів. Він являє собою варіацію традиційної NFA-машини (недетермінірованного кінцевого автомата), аналогічно тим, які використовуються в Perl, Python, Emacs і Tcl. Заміни запропонованих варіантів в рядку здійснює саме він.
1. Основи регулярних виразів
Метасимволи - це спеціальні символи, що задають команди, а також керуючі послідовності, які працюють подібно керуючим послідовностям MQL5 і C #. Такі символи предваряются зворотним слешем (\), кожен з них має особливе призначення.
У таблицях метасимволу регулярних виразів MQL5 і C # згруповані за змістом.
1.1. Класи символів:
Символ Значення Приклад Відповідає [...] Будь-який із символів, зазначених у дужках [az] В заданій стрічці може бути будь-який символ англійського
алфавіту в нижньому регістрі [^ ...] Будь-який із символів, не зазначених в дужках [^ 0-9] В заданій стрічці може бути будь-який символ, крім цифри. Будь-який символ, крім перекладу рядки або іншого роздільник Unicode-рядка ta.d "trad" в рядку "trade" \ w Будь текстовий символ, який не є пропуском, знаком табуляції і т.п. \ W "M", "Q", "L", "5" в рядку "MQL 5" \ W Будь-який символ, який не є текстовим символом \ W "", "." в рядку "MQL 5." \ S Будь символ пробілу з набору Unicode \ w \ s "L" в рядку "MQL 5" \ S Будь непробельний символ з набору Unicode. Зверніть увагу,
що символи \ w і \ S - це не одне і те ж \ S "M", "Q", "L", "5", "." в рядку
"MQL 5." \ D Будь ASCII-цифри. Еквівалентно [0-9] \ d "5" в "MQL 5."
1.2. Символи повторення:
Символ Значення Приклад Відповідає {n, m} Відповідає попереднього шаблону, повторенням не менше n і не більше m разів s {2,4} "Press", "ssl", "progressss" {n,} Відповідає попереднього шаблону, повторенням n або більше разів s {1,} "ssl" {n} відповідає в точності n екземплярів попереднього шаблону s {2} "Press", "ssl", але не "progressss"? Відповідає нулю або одному примірнику попереднього шаблону;
попередній шаблон є необов'язковим Еквівалентно {0,1}
+ Відповідає одному або більше примірників попереднього шаблону Еквівалентно {1,}
* Відповідає нулю або більше примірників попереднього шаблону Еквівалентно {0,}
1.3. Символи регулярних виразів вибору:
Символ Значення Приклад Відповідає | Відповідає або подвираженія зліва, або подвираженія справа (аналог логічного операції АБО). 1 (1 | 2) 0 "110", "120" в рядку
"100, 110, 120, 130" (...) Групування. Групує елементи в єдине ціле, яке може використовуватися з символами *, +,?, | і т.п.
Також запам'ятовує символи, що відповідають цій групі для використання в наступних посиланнях.
(?: ...) Тільки угруповання. Групує елементи в єдине ціле, але не запам'ятовує символи, що відповідають цій групі.
1.4. Якірні символи регулярних виразів:
Символ Значення Приклад Відповідає ^ Відповідає початку строкового вираження або початку рядка при багаторядковому пошуку. ^ Hello "Hello, world", але не "Ok, Hello world" тому що в цьому рядку слово
"Hello" знаходиться не на початку $ Відповідає кінця строкового вираження або кінця рядка при багаторядковому пошуку. Hello $ "World, Hello" \ b Відповідає кордоні слова, тобто відповідає позиції між символом \ w і символом \ W
або між символом \ w і початком або кінцем рядка. \ B (my) \ b В рядку "Hello my world" вибере слово "my"
Більш детально ознайомитися з елементами регулярних виразів ви можете, прочитавши статтю на офіційному сайті Microsoft .
2. Особливості реалізації регулярних виразів для MQL5
2.1. Сторонні файли, що зберігаються в папці Internal
Для максимально близькою реалізації RegularExpressions для MQL5 до вихідного коду .Net нам треба було також перевести частину сторонніх файлів. Всі вони зберігаються в папці Internal і теж становлять великий інтерес.
Розглянемо уважніше вміст папки Internal.
- Generic - в цій папці розташовані файли для реалізації строго типізованих колекцій, перечіслітеля і інтерфейси для них. Більш докладний опис буде приведено нижче.
- TimeSpan - файли для реалізації структури TimeSpan , Що представляє інтервал часу.
- Array.mqh - в даному файлі реалізований клас Array, для якого, в свою чергу, є ряд статичних методів по роботі з масивами. Наприклад: сортування, бінарний пошук, отримання перечіслітеля, отримання індексу елемента і ін.
- DynamicMatrix.mqh - в цей файл містяться два основні класи для реалізації багатовимірних динамічних масивів. Дані класи є шаблонними, а отже, придатні для стандартних типів і для покажчиків на класи.
- IComparable.mqh - файл, який реалізує інтерфейс IComparable, необхідний для підтримки ряду методів в типізованих колекціях.
- Wrappers.mqh - обгортки для стандартних типів і методи для знаходження хеш-кодів по ним.
У Generic реалізовані три строго типізованих колекції:
- List <T> представляє строго типізований список об'єктів, доступних за індексом. Підтримує методи для пошуку за списком, виконання сортування і інших операцій зі списками.
- Dictionary <TKey, TValue> представляє колекцію ключів і значень.
- LinkedList <T> представляє двусвязний список.
Розглянемо використання List <T> з експерта TradeHistoryParsing. Цей експерт зчитує торговельну історію з .html файлу і фільтрує її по обраним колонок і записів. Торгова історія складається з двох таблиць: Угоди і Ордери. Класи OrderRecord і DealRecord інтерпретують одну запис (кортеж) з таблиць Ордери та Угоди, відповідно. Отже, кожну з таблиць можна уявити як список її записів:
List <OrderRecord *> * m_list1 = new List <OrderRecord *> (); List <DealRecord *> * m_list2 = new List <DealRecord *> ();
Оскільки клас List <T> підтримує методи сортування, значить, об'єкти типу T повинні бути порівнянні між собою. Іншими словами, для цього типу реалізовані операції <,>, ==. У випадку зі стандартними елементами проблем не виникає, але якщо нам потрібно створити List <T>, де T - покажчик на призначений для користувача клас, ми отримаємо помилку. Вирішити цю проблему можна двома способами. По-перше, ми можемо в нашому класі явно перевантажити оператори порівняння. Інше рішення - зробити клас спадкоємцем від інтерфейсу IComparable. Другий варіант значно коротше в реалізації, але при цьому порушується правильність сортування. У випадках, коли виникає необхідність в проведенні сортування для призначених для користувача класів, ми повинні перезапустити всі оператори порівняння, до того ж бажано реалізувати спадкування.
Це лише одна з особливостей класу List <T>. Більш докладніше ми розглянемо його нижче.
Dictionary <TKey, TValue> - свого роду словник з набору значень і відповідних їм унікальних ключів. При цьому до одного ключу може бути прив'язане кілька значень. Типи ключів і значень визначає користувач на етапі створення об'єкта. Як видно з опису, клас Dictionary <TKey, TValue> відмінно підходить на роль хеш-таблиці. Для прискорення роботи з Dictionary <TKey, TValue> необхідно створити новий клас, який є спадкоємцем від класу IEqualityComparer <T> і перевантажити дві функції:
- bool Equals (T x, T y) - функція повертає true, якщо x дорівнює y, і false - в іншому випадку.
- int GetHashCode (T obj) - функція повертає хеш-код від об'єкта obj.
У бібліотеці RegularExpresiions для MQL5 ця особливість використовується для всіх словників, ключами для яких служать рядки.
Реалізація класу StringEqualityComparer:
class StringEqualityComparer: public IEqualityComparer <string> {public: virtual bool Equals (string x, string y) {if (StringLen (x)! = StringLen (y)) {return (false); } Else {for (int i = 0; i <StringLen (x); i ++) if (StringGetCharacter (x, i)! = StringGetCharacter (y, i)) {return (false); }} Return (true); } Int GetHashCode (string obj) {return (:: GetHashCode (obj)); }};
Тепер при створенні нового об'єкта, що належить класу Dictionary <TKey, TValue>, де ключами є рядки, в конструкторі як параметр передамо вказівку на об'єкт StringEqualityComparer:
Dictionary <string, int> * dictionary = new Dictionary <string, int> (new StringEqualityComparer);
LinkedList <T> - це структура даних, яка включає в себе ряд елементів. Кожен елемент містить інформаційну частину і два покажчика: на попередній і нижченаведений елементи. Відповідно, два знаходяться поруч елемента взаємно посилаються один на одного. Вузли такого списку реалізуються об'єктами LinkedListNode <T>. У кожному такому вузлі міститься стандартний набір: значення, покажчик на список і покажчики на сусідні вузли.
Також для всіх трьох вищеописаних колекцій реалізовані нумератори. Нумератор - це об'єкт, який представляє собою узагальнений інтерфейс IEnumerator <T>. IEnumerator <T> дозволяє реалізувати повний обхід по колекції незалежно від її структури.
Для отримання перечіслітеля необхідно викликати метод GetEnumerator () від об'єкта, клас якого реалізує інтерфейс IEnumerable:
List <int> * list = new List <int> (); list.Add (0); list.Add (1); list.Add (2); IEnumerator <int> * en = list.GetEnumerator (); while (en.MoveNext ()) {Print (en.Current ()); } Delete en; delete list;
В даному прикладі ми пробігаємо по всьому списку і друкуємо кожне значення. Все це можна було зробити, організувавши звичайний цикл for, але найчастіше підхід з використанням перечіслітеля зручніше. Зокрема, таке рішення підходить, якщо потрібно здійснити прохід по Dictionary <TKey, TValue>.
2.2. Особливості бібліотеки RegularExpressions для MQL5.
1. Для підключення всього функціоналу регулярних виразів в наш проект потрібно додати наступний фрагмент:
#include <RegularExpressions \ Regex.mqh>
2. Через відсутність в мові MQL5 областей імен, а отже - і такого модифікатора доступу, як internal , Ми маємо доступ до всіх внутрішніх класів бібліотеки і багатьом методам для них. По суті, це є зайвим для роботи з регулярними виразами.
Для роботи з регулярними виразами нас будуть цікавити класи:
- Capture - представляє результати однієї успішної записи частини виразу.
- CaptureCollection - представляє набір записів, зроблених однією групою.
- Group - представляє результати окремої групи записи.
- GroupCollection - повертає набір записаних груп в одному зіставленні.
- Math - представляє результати з окремого збігу регулярного виразу.
- MathCollection - представляє набір успішних збігів, виявлених шляхом ітеративного застосування шаблону регулярного виразу до вхідному рядку.
- Regex - представляє незмінне регулярний вираз.
До того ж до вищепереліченого ми будемо використовувати:
- MatchEvaluator - покажчик на функцію, який представляє метод, що викликається кожен раз, коли виявлено збіг регулярного виразу.
- RegexOptions - перерахування, яке надає значення для використання при завданні параметрів регулярних виразів.
RegexOptions - неповна копія вихідного перерахування з .Net і включає в себе наступні елементи:
Параметр Опис None Параметри не встановлені. IgnoreCase Регістр при пошуку збігів не враховується. Multiline Вказує багатостроковий режим. ExplicitCapture Чи не захоплювати неіменовані групи. Єдині допустимі виділення - це явно іменовані або нумеровані групи в форматі (? <Ім'я> частина виразу). Singleline Вказує однорядковий режим. IgnorePatternWhitespace Усуває з шаблону роздільників без escape-послідовності і включає коментарі, помічені символом "#". RightToLeft Вказує, що пошук буде виконаний в напрямку справа наліво, а не зліва направо. Debug Вказує, що програма працює під отладчиком. ECMAScript Включає ECMAScript-сумісний поведінку для вираження. Це значення може бути використано тільки разом зі значеннями IgnoreCase і Multiline.
Ці опції використовуються при створенні нового об'єкта класу Regex або при викликах його статичних методів.
Приклади використання всіх цих класів, покажчика та перерахування ви можете знайти в вихідному коді експерта Tests.mq5.
3. Як і у версії під .Net, в даній бібліотеці реалізовано сховище (статична кеш-пам'ять) регулярних виразів. Все неявно створені регулярні вирази (екземпляри класу Regex) заносяться в це сховище. Такий підхід прискорює роботу скриптів, оскільки відпадає необхідність заново будувати регулярні вирази, якщо його шаблон збігається з одним з вже наявних. За замовчуванням розмір сховища дорівнює 15. Метод Regex :: CacheSize () повертає або задає максимальну кількість записів в поточній статичної кеш-пам'яті скомпільованих регулярних виразів.
4. Вищезазначене сховище необхідно очищати. Для цього викликається статична функція Regex :: ClearCache (). Це рекомендується робити тільки після того, як ви закінчили роботу з регулярними виразами, інакше велика ймовірність видалення потрібних покажчиків і об'єктів.
5. Синтаксис мови C # дозволяє ставити перед рядками символ '@' для ігнорування всіх знаків форматування. У MQL5 такий підхід не передбачений, тому всі керуючі символи в шаблоні регулярних виразів потрібно прописувати явно.
3. Приклад розбору торгової історії
Увага! Приклади, представлені в даній статті, відтворюються тільки за умови того, що на комп'ютер вже встановлена бібліотека RegularExpressions для MQL5 .
Даний приклад має на увазі наступні операції.
- Читання торгової історії з пісочниці в форматі .html файлу.
- Вибір однієї з двох таблиць (таблиць "Ордери" або таблиці "Угоди") для подальшої роботи з нею.
- Вибір фільтрів для таблиці.
- Графічне представлення відфільтрованої таблиці.
- Коротка математична статистика по відфільтрованої таблиці.
- Можливість збереження відфільтрованої таблиці.
Всі ці шість пунктів реалізовано в експерта TradeHistoryParsing.mq5.
Для роботи з експертом насамперед необхідно завантажити торговельну історію. Для цього в торговому терміналі MetaTrader5 на панелі "Інструменти" переходимо у вкладку "Історія", правим кліком відкриваємо діалогове вікно, вибираємо пункт "Звіти" і далі - HTML (InternetExplorer).
Зберігаємо файл в пісочниці (\ MetaTrader 5 \ MQL5 \ Files).
Тепер при запуску експерта в діалоговому вікні переходимо у вкладку "Вхідні параметри" і в полі file_name вводимо ім'я нашого файлу:
Тепер після натискання "ОК" з'явиться сам інтерфейс експерта:
Як вже говорилося вище, обидві таблиці представлені в експерта у вигляді двох типізованих листів: List <OrderRecord *> і List <DealRecord *>.
Конструктори для класів OrderRecord і DealRecord приймають в якості параметрів масив рядків, який переставляє з себе одну запис з таблиці.
Для створення цих масивів нам і знадобляться регулярні вирази. Весь розбір історії відбувається в конструкторі класу TradeHistory, також в цьому класі зберігаються уявлення обох таблиць і реалізовані методи по їх фільтрації. Конструктор даного класу приймає один параметр - path, в нашому випадку це ім'я .html файлу історії:
TradeHistory (const string path) {m_file_name = path; m_handel = FileOpen (path, FILE_READ | FILE_TXT); m_list1 = new List <OrderRecord *> (); m_list2 = new List <DealRecord *> (); Regex * rgx = new Regex ( "(>) ([^ <>] *) (<)"); while (! FileIsEnding (m_handel)) {string str = FileReadString (m_handel); MatchCollection * matches = rgx.Matches (str); if (matches.Count () == 23) {string in [11]; for (int i = 0, j = 1; i <11; i ++, j + = 2) {in [i] = StringSubstr (matches [j] .Value (), 1, StringLen (matches [j] .Value () ) - 2); } M_list1.Add (new OrderRecord (in)); } Else if (matches.Count () == 27) {string in [13]; for (int i = 0, j = 1; i <13; i ++, j + = 2) {in [i] = StringSubstr (matches [j] .Value (), 1, StringLen (matches [j] .Value () ) - 2); } M_list2.Add (new DealRecord (in)); } Delete matches; } FileClose (m_handel); delete rgx; Regex :: ClearCache (); }
Як видно з коду даного конструктора, для розбору торгової історії ми використовуємо тільки одне регулярний вираз з шаблоном "(>) ([^ <>] *) (<)". Розглянемо цей шаблон докладніше:
(>) Пошук символу '>' (^ [<>] *) Будь-який символ, крім '>' і '<', що повторюється нуль або більше разів (<) Пошук символу '<'
Дане регулярний вираз шукає все підрядка, які починаються з '>' і закінчуються '<'. Текст же, який знаходиться між ними, не повинен починатися з '<' або '>'. Простіше кажучи, ми отримуємо тест між тегами в .html файлі, по краях якого ще будуть непотрібні дужки, їх ми приберемо пізніше. Всі знайдені підрядка ми зберігаємо в MathcCollection - колекції всіх подстрок, які відповідають шаблоном регулярного виразу і знайдених в заданій стрічці. Через структури .html файлу ми точно можемо визначити, є наша рядок записом з таблиці Ордерів, записом з таблиці Угод або інший рядком, просто порахувавши кількість збігів. Так, рядок є записом таблиці Ордерів, якщо кількість її збігів дорівнює 23, таблиці Угод - якщо збігів 27. В іншому випадку цей рядок нас не цікавить. Тепер з нашої колекції ми здобуваємо все парні елементи (в непарних будуть рядки "> <"), обрізаємо перший і останній символ і записуємо готову рядок в масив:
in [i] = StringSubstr (matches [j] .Value (), 1, StringLen (matches [j] .Value ()) - 2);
При цьому після прочитання кожної нової рядки потрібно видаляти колекцію збігів. Після прочитання всього файлу необхідно закрити його, видалити регулярний вираз і почистити буфер регулярних виразів.
Тепер нам необхідно реалізувати фільтрацію таблиць, а саме: вибравши деяку колонку і певне значення з неї, отримати урізану таблицю. У нашому випадку з листа ми повинні отримати подлист. Для це ми можемо створити новий лист, організувати повний перебір всіх елементів старого листа і, якщо він задовольняє заданим умовам, додавати його в новий лист.
Але є й інший спосіб на основі методу FindAll (Predicate match) для List <T>. Він витягує всі елементи, що задовольняють умовам зазначеного предиката, який є покажчиком на функцію і має вигляд:
typedef bool (* Predicate) (IComparable *);
Про інтерфейс IComparable вже було розказано раніше.
Залишилося лише реалізувати саму функцію match, де вже заздалегідь відомо правило, за яким ми приймаємо або відхиляємо елемент листа. У нашому випадку це номер колонки і значення в ній. Для вирішення цього завдання в класі Record, який є спадкоємцем для класів OrderRecord і DealRecord, є два статичних методу SetIndex (const int index) і SetValue (const string value). Ці методи приймають і запам'ятовують номер колонки і значення в ній. Потім ці дані як раз і будуть використовуватися при реалізації нашого методу для пошуку:
static bool FindRecord (IComparable * value) {Record * record = dynamic_cast <Record *> (value); if (s_index> = ArraySize (record.m_data) || s_index <0) {Print ( "Iindex out of range."); return (false); } Return (record.m_data [s_index] == s_value); }
Тут s_index - статична змінна, значення якої задається методом SetIndex, а s_value - статична змінна, значення якої задається методом SetValue.
Тепер, задаючи потрібні нам значення номера колонки і значення в ній, ми з легкістю отримаємо урізану версію нашого листа:
Record :: SetValue (value); Record :: SetIndex (columnIndex); List <Record *> * new_list = source_list.FindAll (Record :: FindRecord);
Саме ці відфільтровані листи будуть відображатися в графічному інтерфейсі експерта.
При необхідності є можливість збереження цих відфільтрованих таблиць в .csv файли. Файл буде збережений також в пісочницю під назвою Result.csv.
ВАЖЛІВО! При збереженні файлів їм завжди присвоюється один і той же ім'я. Таким чином, якщо виникає необхідність збереження двох і більше таблиць, потрібно зберігати їх по одній і перейменовувати. Інакше буде відбуватися перезапис одного і того ж файлу.
4. Приклад розбору результатів оптимізації експерта
Даний приклад обробляє .xml файл результату оптимізації експерта з терміналу MetaTrader5. У ньому реалізовано графічне представлення для даних, отриманих в ході оптимізації, а також можливість їх фільтрації. Всі дані діляться на дві таблиці:
- "Tester results table" - в неї входять всі статистичні дані, отримані в ході тестування;
- "Input parameters table" - тут зберігаються всі значення вхідних змінних. Для цієї таблиці встановлений ліміт в десять вхідних параметрів. Якщо параметрів більше, то вони не будуть відображатися.
Для встановлення фільтра на одну з таблиць необхідно вибрати ім'я колонки, по якій буде проходити фільтрація, і задати діапазон значень.
Графічний інтерфейс прикладу має вигляд:
На даному малюнку показано відображення таблиці "Tester results table" з активними колонками: "Pass", "Result", "Profit Factor", "Recovery Factor" і двома фільтрами:
- Значення в колонці "Pass" повинні належати діапазону значень [0; 10];
- Значення в колонці "Profit Factor" повинні належати діапазону значень [0.4; 0.5].
5. Короткий опис прикладів з бібліотеки RegularExpressions для MQL5
Крім двох описаних експертів, до бібліотке RegularExpressions для MQL5 додається 20 прикладів. У них будуть реалізовані різні можливості регулярних виразів і даної бібліотеки в цілому. Всі вони знаходяться в експерта Tests.mq5:
Розглянемо, які конкретно особливості та можливості бібліотеки задіяні в кожному з прикладів.
- MatchExamples - показує два можливих варіанти перебору всіх сопаденій (Match) - через створення MatchCollection або шляхом використання методу Match.NextMatch ().
- MatchGroups - показує спосіб отримання результатів окремої групи записи (Group) і подальшу роботу з ними.
- MatchResult - демонструє використання методу Match.Result (string), який повертає розширення зазначеного шаблону заміни.
- RegexConstructor - показує 3 різних варіанти створення класу Regex: на основі шаблону, шаблона з вказаними параметрами, шаблона з параметрами і значенням, що вказує, як довго метод порівняння з шаблоном повинен намагатися знайти збіг, перш ніж час очікування закінчиться.
- RegexEscape - демонструє роботу методу Regex :: Escape (string).
- RegexExample - показує процес створення регулярних виразів і їх подальшу обробку.
- RegexGetGroupNames - показує приклад використання методу Regex.GetGroupNames (string);
- RegexGetGroupNumbers - показує приклад використання методу Regex.GetGroupNumbers (int);
- RegexGroupNameFromNumber - показує приклад використання методу Regex.GroupNameFromNumber (int);
- RegexIsMatch - показує приклад використання всіх варіантів статичного методу Regex :: IsMatch ();
- RegexReplace - показує приклад використання основних варіантів статичного методу Regex :: Replace ();
- RegexSplit - показує приклад використання основних варіантів статичного методу Regex :: Split ();
- Capture - приклад роботи з результатом однієї успішної записом частини виразу (Capture).
- CaptureCollection - приклад роботи з набором записів, зроблених однією групою записи (CaptureCollection).
- Group - приклад роботи з результатом окремої групи записи (Group).
- GroupCollection - приклад роботи з набором записаних груп в одному зіставленні (GroupCollection).
- MatchCollectionItem - створення MatchCollection статичним методом Regex :: Matches (string, string);
- MatchEvaluator - приклад створення покажчика на функцію типу MatchEvaluator і його використання.
- RegexMatchCollectionCount - демонстрація методу MatchCollection.Count ();
- RegexOptions - демонстрація впливу параметра RegexOptions на обробку регулярного виразу.
Більшість прикладів перетинаються по функціональним можливостям і служать здебільшого для тестування роботи бібліотеки.
Висновок
В даній статті коротко розказано про можливості регулярних виразів і їх застосуванні. Для більш детального ознайомлення рекомендуємо почитати статті за вказаними нижче посиланнями. Синтаксис регулярних виразів на .Net багато в чому збігається і з реалізацією на MQL5, тому всі довідки від Microsoft будуть актуальні, хоча б частково. Те ж саме стосується і класів з папки Internal.
ПОСИЛАННЯ
- http://professorweb.ru/my/csharp/charp_theory/level4/4_10.php
- https://habrahabr.ru/post/115825/
- https://habrahabr.ru/post/115436/
- https://msdn.microsoft.com/ru-ru/library/hs600312.aspx
- https://msdn.microsoft.com/ru-ru/library/ae5bf541.aspx