1
<appendix id="regular-expressions">
5
>&Anders.Lund; &Anders.Lund.mail;</author>
6
<othercredit role="translator"
14
>yurchor@ukr.net</email
18
>Переклад українською</contrib
25
>Формальні вирази</title>
28
>У цьому додатку наведено короткий, але, як сподіваються автори, достатній і інформативний вступ до світу <emphasis
29
>формальних виразів</emphasis
30
>. Тут наведено документацію щодо формальних виразів у тому вигляді, у якому вони використовуються у &kappname;, і який не є сумісним ні з формальними виразами у perl, ні з формальними виразами, наприклад, у <command
40
>За допомогою <emphasis
41
>формальних виразів</emphasis
42
> можна описати можливий вміст рядка тексту так, щоб ваш опис був зрозумілим програмі і вона змогла визначати відповідність тексту шуканому рядку, а також, у випадку програм з додатковими можливостями, зберігати знайдені фрагменти для наступного використання.</para>
45
>Приклад: припустімо, вам потрібно знайти у тексті абзаци, які починаються зі слів <quote
49
>, за якими слідує одна з форм дієслова <quote
54
>Якщо б ви виконували пошук у звичайний спосіб, ви мали б почати з пошуку імені, <quote
56
>, можливо у супроводі <quote
58
>, десь так: <userinput
59
>Іван говори</userinput
60
>, серед відповідників вам слід би було відкинути ті, які стоять не на початку абзацу, а також ті, у яких літери <quote
62
> не є літерами слів <quote
66
> тощо. Потім, звичайно ж, вам слід було б повторити пошук для прізвища...</para>
69
>За допомогою формальних виразів завдання з пошуку виконується в одну дію і з вищим рівнем точності.</para>
72
>Щоб досягти цього, за допомогою формальних виразів визначаються правила, за допомогою яких створюється узагальнена форма рядка пошуку. У нашому прикладі це правило можна висловити буквально так: <quote
73
>Рядок, який починається з <quote
77
> (перед цим словом може бути до 4 пробілів або символів табуляції), продовжується пробілом, за яким йде слово <quote
79
>, яке закінчується на <quote
84
>. Все це визначає формальний вираз:</para
87
>^[ \t]{0,4}(Іван|Франко) говори(ть|в)</userinput
91
>У наведеному вище прикладі продемонстровано всі чотири компоненти сучасних формальних виразів, а саме:</para>
108
>Зворотні посилання</para
113
>Символ каретки (<literal
115
>) на початку виразу є умовним виразом, який визначає, що наступний рядок має розпочинати рядок у тексті.</para>
121
>(Іван|Франко) говори(ть|в)</literal
122
> є шаблонами. Перший з них визначає <emphasis
123
>клас символів</emphasis
124
>, до якого належить пробіл або символ горизонтальної табуляції; у другому шаблоні міститься спочатку підшаблон, який визначає рядок <literal
130
>, потім рядка <literal
132
> і нарешті підшаблону, що визначає закінчення: <literal
143
> є лічильником, який повідомляє інструментові пошуку, що рядок знаходиться <quote
144
>будь-де, за від 0 до 4 рядками, вказаними раніше</quote
148
>Програмне забезпечення, яке працює з формальними виразами, підтримує концепцію <emphasis
149
>зворотних посилань</emphasis
150
>, використання цієї концепції надає змогу зберегти повністю знайдену частину рядка або підрядки, позначені круглими дужками, а потім у певний спосіб використати ці посилання. Отже, ми можемо повністю позбутися ручної роботи з пошуку рядка (під час пошуку за допомогою формального виразу у текстовому документі, відкритому у редакторі, цей рядок буде позначено як виділений), пошуку імені або навіть фраз з різними закінченнями у дієслів.</para>
153
>Разом, формальний вираз визначає саме той рядок, який ми бажали знайти, і лише у потрібному місці тексту.</para>
156
>У наступних розділах буде докладно описано побудову і використання шаблонів, класів символів, умовних виразів, лічильників і зворотних посилань. Нарешті у останньому розділі ви знайдете декілька корисних прикладів.</para>
160
<sect1 id="regex-patterns">
166
>Шаблони складаються з рядків і класів символів. У шаблонах можуть міститися підшаблони, тобто шаблони, взяті у круглі дужки.</para>
170
>Символи керування</title>
173
>У шаблонах, так само як і у класах символів, певні символи мають особливе призначення. Для пошуку цих символів не за значенням, а за візуальним представленням, ці символи слід позначити або <emphasis
174
>екранувати</emphasis
175
>, щоб повідомити рушієві пошуку за формальним виразом, що відповідні символи слід шукати за їх візуальним представленням.</para>
178
>Це завдання можна виконати за допомогою додавання перед символом зворотної навскісної риски (<literal
184
>Рушій пошуку за формальним виразом без додаткових повідомлень ігноруватиме екрановані символи, які не мають спеціального призначення, отже екранування, наприклад, символу <quote
188
>) є безпечним. Якщо ви не пам’ятаєте, чи може символ мати спеціальне призначення, ви можете про всяк випадок його заекранувати.</para>
191
>Екранування, звичайно ж, можна застосовувати і до самого символу зворотної навскісної риски, щоб програма сприймала введену вами зворотну навскісну риску як зворотну навскісну риску, вам слід ввести <userinput
199
>Класи символів і абревіатури</title>
203
>Клас символів</emphasis
204
> — це вираз, якому відповідає один символ з вказаного набору символів. У формальних виразах, класи символів визначаються зазначенням дозволених символів класу у квадратних дужках, <literal
206
>, або за допомогою абревіатур класів, які описано нижче.</para>
209
>Прості класи символів містять один або декілька буквених символів, наприклад, <userinput
211
> (це означає одну з літер: <quote
218
>[0123456789]</userinput
219
> (цей клас визначає одну цифру).</para>
222
>Оскільки для літер і цифр характерний певний порядок (абетка або порядок цифр), ви можете скорочувати запис за допомогою діапазонів: <userinput
224
> рівнозначний до <userinput
229
>[0123456789]</userinput
230
>. Можна також використовувати комбінації таких конструкцій, наприклад, <userinput
231
>[a-fynot1-38]</userinput
232
> (звичайно ж, остання комбінація відповідає одному з символів <quote
263
>Оскільки великі літери відрізняються від своїх малих еквівалентів, для створення класу символів, у якому б регістр не мав значення, з літер <quote
267
>, вам слід записати <userinput
272
>Звичайно ж можна створити і <quote
273
>негативний клас</quote
274
>, до якого б входили <quote
275
>всі літери окрім вказаних</quote
276
>. Для запису такого класу вам слід скористатися символом каретки (<literal
278
>) на початку запису класу: </para>
283
> відповідає будь-якому символу, <emphasis
294
>Окрім звичайних символів, передбачено використання деяких скорочень, які спрощують запис формальних виразів: <variablelist>
303
>Цей рядок відповідає символу дзвінка у <acronym
316
>Цей рядок відповідає символу зміни сторінки у <acronym
329
>Цей рядок відповідає символу зміни рядка у <acronym
331
> (LF, 0x0A, символ нового рядка у Unix).</para
342
>Цей рядок відповідає символу повернення каретки у <acronym
355
>Цей рядок відповідає символу горизонтальної табуляції у <acronym
368
>Цей рядок відповідає символу вертикальної табуляції у <acronym
381
>Такий рядок відповідає символу Unicode з шістнадцятковим номером hhhh (у межах від 0x0000 до 0xFFFF). \0ooo (тобто \нульo ooo) відповідає символу з <acronym
383
>/Latin-1 з вісімковим номером ooo (у межах від 0 до 0377).</para
394
>Цей рядок відповідає будь-якому символу (зокрема символу нового рядка).</para
405
>Цей рядок відповідає будь-якій цифрі. Він рівнозначний до <literal
418
>Цей рядок відповідає будь-якому символу, окрім цифри. Він рівнозначний до <literal
433
>Цей рядок відповідає символу проміжку між символами. З практичної точки зору, він рівнозначний до <literal
446
>Цей рядок відповідає символу, який не є пробілом. З практичної точки зору, цей рядок еквівалентний до <literal
461
>Цей рядок відповідає будь-якому <quote
462
>символу слова</quote
463
> — у нашому випадку, літері або цифрі. Зауважте, що символ підкреслювання (<literal
465
>) не вважається символом слова, на відміну від формальних виразів у мові Perl. Цей рядок еквівалентний до рядка <literal
466
>[a-zA-Z0-9]</literal
478
>Цей рядок відповідає будь-якому символу, який не є символом запису слів, тобто будь-якому символу, який не є літерою або цифрою. Рядок еквівалентний до рядка <literal
479
>[^a-zA-Z0-9]</literal
492
>Класи-скорочення можна використовувати в межах загальних класів, наприклад, щоб знайти літеру слова, символ пробілу або крапку, ви можете скористатися записом <userinput
498
>Позначення POSIX для класів, <userinput
499
>[:<назва класу>:]</userinput
500
>, у поточній версії не підтримується.</para
505
>Символи з особливим призначенням у класах символів</title>
508
>Перелічені далі символи мають особливе призначення у конструкціях класів символів <quote
510
>, отже для включення їх за візуальним значенням до класу ці символи слід екранувати:</para>
520
>Завершує визначення класу символів. Цей символ слід екранувати, якщо він не є найпершим символом у класі (можна використовувати одразу за неекранованим символом каретки)</para
527
> (знак вставки)</term>
530
>Змінює значення вказаного класу на протилежне, якщо є першим символом класу. Цей символ слід екранувати, якщо він є першим символом класу.</para
540
>Визначає діапазон. Цей символ завжди слід екранувати, якщо він визначає символ у класі символів.</para
547
> (зворотна навскісна риска)</term>
550
>Символ керівної послідовності. Цей символ завжди слід екранувати, якщо він потрібен вам як символ зворотної навскісної риски.</para
563
>Варіанти: пошук <quote
568
>Якщо вам потрібно знайти один з декількох варіантів шаблонів, ви можете відокремити ці шаблони символом <literal
570
> (вертикальною рискою).</para>
573
>Наприклад, щоб знайти один з рядків, <quote
577
>, вам слід скористатися виразом <userinput
578
>Іван|Юрій</userinput
590
>Підшаблони</emphasis
591
> — це шаблони взяті у круглі дужки, у світі формальних виразів існує декілька способів використання підшаблонів.</para>
596
>Визначення варіантів</title>
599
>Ви можете скористатися підшаблоном, щоб згрупувати набір варіантів у більший шаблон. Варіанти відокремлюються символом <quote
601
> (вертикальною рискою).</para>
604
>Наприклад, для того, щоб знайти одне зі слів <quote
610
>, ви можете скористатися шаблоном <userinput
611
>int|float|double</userinput
612
>. Якщо вам потрібно знайти одне з цих слів, і вам відомо, що за цим словом має йти пробіл, а потім якісь літери, згрупуйте варіанти у підшаблон: <userinput
613
>(int|float|double)\s+\w+</userinput
621
>Збереження знайденого тексту (зворотні посилання)</title>
624
>Якщо вам потрібно скористатися зворотним посиланням, скористайтеся групуванням у підшаблон для того, щоб рушій запам’ятав потрібну частину шаблону.</para>
627
>Наприклад, якщо вам потрібно знайти два однакових слова, відокремлені комою і, можливо, пробільними символами, ви можете скористатися формальним виразом <userinput
628
>(\w+),\s*\1</userinput
629
>. За допомогою підшаблону <literal
631
> буде знайдено послідовність символів слів, збіг з формальним виразом буде зареєстровано, якщо за цією послідовністю буде кома, 0 або більше пробільних символів і така сама послідовність символів слів. (Рядок <literal
633
> відповідає <emphasis
634
>першому підшаблону, взятому у круглі дужки</emphasis
638
>See also <link linkend="backreferences"
639
>Back references</link
645
<sect3 id="lookahead-assertions">
647
>Умовні вирази з перевіркою</title>
650
>Умовний вираз з перевіркою — це підшаблон, що починається з символів <literal
657
>Наприклад, для того, щоб знайти рядок <quote
659
>, за яким не буде рядка <quote
661
>, можна скористатися таким виразом: <userinput
662
>Bill(?! Gates)</userinput
663
>. (Таким чином буде знайдено послідовності <quote
667
>, але проігноровано всі інші варіанти.)</para>
670
>Підшаблони, які було використано для перевірки умови, не будуть запам’ятовуватися рушієм пошуку.</para>
673
>Див. також <link linkend="assertions"
681
<sect2 id="special-characters-in-patterns">
683
>Символи зі спеціальним значення у шаблонах</title>
686
>Перелічені нижче символи мають особливе призначення в межах шаблону, отже, якщо вам потрібно буде знайти ці символи за візуальним представленням, вам слід буде екранувати їх: <variablelist>
692
> (зворотна навскісна риска)</term>
695
>Символ керівної послідовності.</para
703
> (знак вставки)</term>
706
>Умовний початок рядка.</para
717
>Умовне завершення рядка.</para
725
> (ліва і права круглі дужки)</term>
728
>Визначення підшаблону.</para
736
> (ліва і права фігурні дужки)</term>
739
>Визначення числових лічильників.</para
747
> (ліва і права квадратні дужки)</term>
750
>Визначення класів символів.</para
758
> (вертикальна риска)</term>
761
>Логічне АБО. Відокремлює варіанти значення.</para
769
> (знак «плюс»)</term>
772
>Лічильник, 1 або більше.</para
783
>Лічильник, 0 або більше.</para
791
> (знак питання)</term>
794
>Необов’язковий символ. Може бути інтерпретовано яка лічильник, 0 або 1.</para
806
<sect1 id="quantifiers">
811
>За допомогою <emphasis
812
>лічильників</emphasis
813
> можна виконувати пошук вказаної кількості або певного діапазону кількостей відповідників символу, класу символів або підшаблону.</para>
816
>Лічильники слід вказувати між фігурними дужками (<literal
820
>). У загальному випадку вони виглядають так: <literal
821
>{[мінімальна кількість][,[максимальна кількість]]}</literal
825
>Використання найкраще пояснюється прикладом: <variablelist>
834
>Точно один збіг.</para
845
>Жодного або 1 збіг.</para
856
>Те саме, але меншими зусиллями ;)</para
867
>Не менше 5, але не більше 10 збігів.</para
878
>Не менше 5 збігів, без обмежень згори.</para
887
>Крім того, існує декілька скорочень: <variablelist>
896
>те саме, що і <literal
898
>, шукати без обмеження на кількість відповідників.</para
906
> (знак «плюс»)</term>
909
>те саме, що і <literal
911
>, принаймні один відповідник.</para
919
> (знак питання)</term>
922
>те саме, що і <literal
924
>, жодного або один відповідник.</para
938
>За використання лічильників без зазначення максимальної кількості, типово, буде виконано пошук якомога більшої кількості відповідників формального виразу, така поведінка називається <emphasis
943
>У сучасних рушіях пошуку за формальними виразами передбачено можливість <quote
944
>вимикання жадібності</quote
945
>, забезпечення доступу до цієї можливості є проблемою лише графічного інтерфейсу. Наприклад, у діалоговому вікні пошуку за формальним виразом може бути поле для позначки з міткою <quote
946
>Мінімальна кількість збігів</quote
947
>, а також певним чином позначено, що жадібність є типовою поведінкою.</para>
953
>Приклади використання</title>
956
>Ось декілька прикладів використання лічильників</para>
963
>^\d{4,5}\s</userinput
967
>Буде знайдено цифри у <quote
972
>567 одинадцять</quote
986
>Буде знайдено один або декілька пробільних символів</para
997
>Буде знайдено <quote
1016
>Буде знайдено <quote
1019
><closeditem/></quote
1023
><openitem></quote
1034
<sect1 id="assertions">
1036
>Умовні вирази</title>
1039
>За допомогою <emphasis
1040
>умовних виразів</emphasis
1041
> відповідники формального виразу буде знайдено лише за виконання певних керованих умов.</para>
1044
>За використання умовного виразу не буде виконуватися пошук певного символу, рушій скоріше вивчатиме оточення можливого відповідника формального виразу і визначатиме, чи той це вираз, який вам потрібен. Наприклад, за використання умови <emphasis
1045
>межа слова</emphasis
1046
> рушій пошуку не намагатиметься знайти символ, який не є символом слова, поряд зі знайденим словом, — рушій просто переконається, що цей символ не є символом слова. Це означає, що за використання умовного виразу, рядок буде знайдено і там, де пробільного символу немає, наприклад, наприкінці рядка.</para>
1049
>У деяких умовних виразах можуть міститися шаблони, але за їх використання виконуватиметься лише перевірка на збіг рядка з вказаним шаблоном, — результат перевірки не буде включено до результатів пошуку.</para>
1052
>У формальних виразах, описаних у цій документації, підтримуються такі умовні вирази: <variablelist>
1058
> (каретка: початок рядка)</term>
1061
>Пошук на початку рядка.</para
1063
>За виразом <userinput
1065
> буде знайдено рядок <quote
1068
>Петре, агов!</quote
1069
>, але не у рядку <quote
1070
>Агов, Петре!</quote
1079
> (кінець рядка)</term>
1082
>Пошук наприкінці рядка.</para>
1085
>За виразом <userinput
1087
> буде знайдено останнє «ти» у рядку <quote
1088
>Це зробив не ти?</quote
1089
>, але нічого не буде знайдено у рядку <quote
1090
>Це ж не ти зробив?</quote
1100
> (межа слова)</term>
1103
>Пошук рядка, з одного боку якого стоїть символ запису слів, а з іншого — символ, який не використовується для запису слів.</para>
1105
>Цей вираз корисний для перевірки на те, чи завершується у певному місці слово, наприклад під час пошуку цілого слова. Вираз <userinput
1107
> буде знайдено як окреме слово <quote
1110
>Він увійшов у вікно</quote
1111
>, але не як частину <quote
1124
> (відсутність межі слова)</term>
1127
>Пошук всіх відповідників, які не буде пропущено за використання умовного виразу <quote
1131
>Такий вираз можна використовувати, наприклад, для пошуку внутрішніх частин слів: вираз <userinput
1133
> буде знайдено у слові <quote
1135
>, але не у слові <quote
1138
>Бачив у кіно</quote
1146
>(?=ШАБЛОН)</userinput
1147
> (перевірка на збіг)</term>
1150
>За допомогою умовного виразу перевірки на збіг можна перевірити на відповідність частину рядка, яку розташовано безпосередньо за можливим відповідником. За використання перевірки на збіг частина рядка вважатиметься невідповідною, якщо за нею не йде вказаний <emphasis
1152
> умовного виразу, але текст цього шаблону не буде додано до результату пошуку.</para>
1154
>За виразом <userinput
1155
>зручно(?=\w)</userinput
1156
> буде знайдено рядок <quote
1161
>Це дуже зручно!</quote
1162
> нічого не буде знайдено.</para>
1169
>(?!ШАБЛОН)</userinput
1170
> (перевірка на відсутність збігу)</term>
1174
>За перевірки на відсутність збігу знайдений рядок не буде вважатися потрібним, якщо за ним йде рядок вказаний як <emphasis
1179
>const \w+\b(?!\s*&)</userinput
1180
> відповідатиме частині <quote
1183
>const char* foo</quote
1184
>, але не частині <quote
1185
>const QString</quote
1187
>const QString& bar</quote
1188
>, оскільки символ <quote
1190
> збігається з шаблоном перевірки на відсутність збігу.</para>
1200
<!-- TODO sect1 id="backreferences">
1203
>Back References</title>