Шпаргалка за регулярними виразами PERL
Глава 6.4. Регулярні вирази
6.4.1. Синтаксис регулярних виразів
Регулярні вислови є зразки для пошуку заданих комбінацій символів в текстових рядках і заміни їх на інші комбінації символів (ці операції називаються відповідно зіставлення зі зразком і підстановка). Регулярний вираз в мові PERL має вигляд
/ Pattern / modifiers
Тут pattern - це рядок, що задає регулярний вираз, а modifiers - необов'язкові однобуквені модифікатори , уточнюючі правила використання цього регулярного виразу.
Регулярний вираз може складатися зі звичайних символів; в цьому випадку воно буде відповідати заданій комбінації символів в рядку. Наприклад, вираз / кат / відповідає виділеним підрядками в наступних рядках: "кат ок", "за кат", "у кат ить". Однак, справжню силу регулярними виразами PERLа надає можливість використання в них спеціальних метасимволов.
символ | опис |
---|---|
\ | Для символів, які зазвичай трактуються буквально, означає, що наступний символ є метасимволом. Наприклад, / n / відповідає букві n, а / \ n / відповідає символу перекладу рядка. Для метасимволов означає, що символ повинен розумітися буквально. Наприклад, / ^ / означає початок рядка, а / \ ^ / відповідає просто символу ^. / \\ / Відповідає зворотної косої межі \. |
^ | Відповідає початку рядка (пор. Модифікатор m ). |
$ | Відповідає кінця рядка (пор. Модифікатор m ). |
. | Відповідає будь-якому символу, крім розриву рядка (пор. Модифікатор s ). |
* | Відповідає повторення попереднього символу нуль або більше разів. |
+ | Відповідає повторення попереднього символу один або більше разів. |
? | Відповідає повторення попереднього символу нуль або один раз. |
(Pattern) | Відповідає рядку pattern і запам'ятовує знайдене відповідність . |
x | y | Відповідає x або y. |
{N} | n - невід'ємне число. Відповідає рівно n входженням попереднього символу. |
{N,} | n - невід'ємне число. Відповідає n або більше входженням попереднього символу. / X {1,} / еквівалентно / x + /. / X {0,} / еквівалентно / x * /. |
{N, m} | n і m - невід'ємні числа. Відповідає не менше ніж n і не більше ніж m входженням попереднього символу. / X {0,1} / еквівалентно / x? /. |
[Xyz] | Відповідає будь-якому символу з ув'язнених в квадратні дужки. |
[^ Xyz] | Відповідає будь-якому символу, крім вкладених у квадратні дужки. |
[A - z] | Відповідає будь-якому символу у вказаному діапазоні. |
[^ A - z] | Відповідає будь-якому символу, крім лежать в зазначеному діапазоні. |
\ a | Відповідає символу дзвінок (BEL). |
\ A | Відповідає тільки початок рядка, навіть з модифікатором m . |
\ b | Відповідає кордоні слова, т. Е. Позиції між \ w і \ W в будь-якому порядку. |
\ B | Відповідає будь-якій позиції, окрім кордону слова. |
\ с X | Відповідає символу Ctrl + X. Наприклад, / \ cI / еквівалентно / \ t /. |
\ C | Відповідає одному байту, навіть при директиві use utf8. |
\ d | Відповідає цифрі. Еквівалентно [0-9]. |
\ D | Відповідає нецифровому символу. Еквівалентно [^ 0-9]. |
\ e | Відповідає символу escape (ESC). |
\ E | Кінець перетворень \ L, \ Q, \ U. |
\ f | Відповідає символу перекладу формату (FF). |
\ G | Відповідає позиції в рядку, що дорівнює pos (). |
\ l | Перетворює наступний символ в нижній регістр. |
\ L | Перетворює символи в нижній регістр до \ E. |
\ n | Відповідає розриву рядків. |
\ p property | Відповідає символам Unicode, що володіє властивістю property. Якщо property задається кількома символами, використовуйте синтаксис \ p {property}. |
\ P property | Відповідає символам Unicode, що не володіє властивістю property. Якщо property задається кількома символами, використовуйте синтаксис \ P {property}. |
\ Q | Додає символ "\" перед метасимвол до \ E. |
\ r | Відповідає символу повернення каретки (CR). |
\ s | Відповідає символу пробілу. Еквівалентно / [\ f \ n \ r \ t] /. |
\ S | Відповідає будь-якому непробельний символу. Еквівалентно / [^ \ f \ n \ r \ t] /. |
\ t | Відповідає символу табуляції (HT). |
\ u | Перетворює наступний символ у верхній регістр. |
\ U | Перетворює символи у верхній регістр до \ E. |
\ w | Відповідає латинської букви, цифри або підкреслення. Еквівалентно / [A-Za-z0-9_] /. |
\ W | Відповідає будь-якому символу, крім латинської букви, цифри або підкреслення. Еквівалентно / [^ A-Za-z0-9_] /. |
\ X | Відповідає послідовності символів Unicode з основного символу і набору діакритичних значків. Еквівалентно висловом / C <(?: \ PM \ pM *)> /. |
\ z | Відповідає тільки кінця рядка, навіть з модифікатором m . |
\ Z | Відповідає тільки кінця рядка або розриву рядків в кінці рядка, навіть з модифікатором m . |
\ n | n - позитивне число. Відповідає n -ї запомненной підрядку . Якщо лівих дужок до цього символу менше, ніж n, і n> 9, то еквівалентно \ 0 n. |
\ 0 n | n - вісімкове число, не більше 377. Відповідає символу з восьмеричним кодом n. Наприклад, / \ 011 / еквівалентно / \ t /. |
\ x n | n - шістнадцяткове число, що складається з двох цифр. Відповідає символу з шістнадцятковим кодом n. Наприклад, / \ x31 / еквівалентно / 1 /. |
\ x {n} | n - шістнадцяткове число, що складається з чотирьох цифр. Відповідає символу Unicode з шістнадцятковим кодом n. Наприклад, / \ x {2663} / еквівалентно / ♣ /. |
6.4.2. модифікатори
Різні операції з регулярними виразами використовують різні модифікатори для уточнення виконуваної операції. Однак, чотири модифікатора мають загальне призначення.
- i
- Ігнорує регістр символів при зіставленні зі зразком. При використанні директиви use locale приведення символів до одного регістру проводиться з урахуванням національної настройки.
- m
- Розглядає вихідну рядок як буфер з кількох рядків тексту, розділених розривами рядків. Це означає, що метасимволу ^ і $ відповідають не тільки початку і кінця всього рядка, але і початку і кінця рядку тексту, обмеженою розривами рядків.
- s
- Розглядає вихідну рядок як єдиний рядок тексту, ігноруючи розриви рядків. Це означає, що метасимвол. відповідає будь-якому символу, включаючи розрив рядка.
- x
- Дозволяє використання прогалин і коментарів. Прогалини, які не мають попереднього символу \ і не укладені в [], ігноруються. Символ # починає коментар, який також ігнорується.
6.4.3. Класи символів Unicode і POSIX
Ми можемо використовувати в регулярних виразах синтаксис
[: Class:]
де class задає назву класу символів POSIX, т. е. мобільного стандарту на мову C. При використанні директиви use utf8 замість класів POSIX можна використовувати класи символів Unicode в конструкції
\ P {class}
В наступній таблиці зведені всі класи символів POSIX, відповідні класи символів Unicode і метасимволу, якщо вони є.
POSIX | Unicode | метасимвол | опис |
---|---|---|---|
alpha | IsAlpha | букви | |
alnum | IsAlnum | Букви і цифри | |
ascii | IsAscii | символи ASCII | |
cntrl | IsCntrl | керуючі символи | |
digit | IsDigit | \ d | цифри |
graph | IsGraph | Букви, цифри і знаки пунктуації | |
lower | IsLower | малі літери | |
IsPrint | Букви, цифри, знаки пунктуації та пробіл | ||
punct | IsPunct | знаки пунктуації | |
space | IsSpace | \ s | символи пробілу |
upper | IsUpper | Прописні літери | |
word | IsWord | \ w | Букви, цифри і підкреслення |
xdigit | IsXDigit | шістнадцятиричні цифри |
Наприклад, десяткове число можна задати будь-яким з наступних трьох способів:
/ \ D + / / [: Digit:] + / / \ P {IsDigit} + / # use utf8
Для вказівки того, що символ не належить до заданого класу, використовуються конструкції
[: ^ Class:] \ P {class}
Наприклад, такі вирази мають однаковий сенс:
[: ^ Digit:] \ D \ P {IsDigit} [: ^ Space:] \ S \ P {IsSpace} [: ^ Word:] \ W \ P {IsWord}
6.4.4. запам'ятовування подстрок
Використання круглих дужок в регулярному виразі приводить до того, що подстрока, відповідна зразком в дужках, запам'ятовується в буфері. Для доступу до n -ї запомненной підрядку всередині регулярного виразу використовується конструкція \ n, а поза ним - $ n, де n може приймати будь-які значення, починаючи з 1. Однак, слід пам'ятати, що PERL використовує вирази \ 10, \ 11 і т . д. як синоніми для вісімкових кодів символів \ 010, \ 011 і т. д. Неоднозначність тут дозволяється так. Символ \ 10 вважається зверненням до 10-ї запомненной підрядку, якщо перед ним в регулярному виразі коштує не менше десяти лівих круглих дужок; в іншому випадку, це символ з восьмеричним кодом 10. Метасимволи \ 1, ... \ 9 завжди вважаються зверненнями до запомненним підрядками. приклади:
if (/(.)\1/) {# шукаємо перший повторюється символ print " '$ 1' - перший повторюється символ \ n"; } if (/ Time: (..) ..) ..) /) {# Витягаємо компоненти часу $ Hours = $ 1; $ Minutes = $ 2; $ Seconds = $ 3; }
Крім змінних $ 1, $ 2, ... є ще кілька спеціальних змінних, в яких зберігаються результати останньої операції з регулярним виразом, а саме:
Мінлива | опис |
---|---|
$ & | Остання знайдений підрядок. |
$ ` | Підрядок перед останньою знайденою підрядком. |
$ ' | Підрядок після останньої знайденої підрядка. |
$ + | Остання після успішної реєстрації подстрока. |
Наведемо приклад:
'AAA111BBB222' = ~ / (\ d +) /; print "$` \ n "; # AAA print "$ & \ n"; # 111 print "$ '\ n"; # BBB222 print "$ + \ n"; # 111
Всі ці спеціальні змінні зберігають свої значення до кінця осяжний блоку або до наступного успішного зіставлення зі зразком.
6.4.5. розширені зразки
PERL містить кілька додаткових конструкцій, які можуть вживатися в регулярних виразах для розширення їх можливостей. Всі ці конструкції полягають в круглі дужки і починаються з символу? , Що відрізняє їх від запам'ятовування подстрок.
- (? # Text)
- Коментар. Вся конструкція ігнорується.
- (? Modifiers - modifiers)
- Вмикає або вимикає задані модифікатори . Модифікатори, які стоять до символу -, включаються, які стоять після нього - вимикаються. приклад:
if (/ aaa /) {...} # зіставлення з урахуванням регістру if (/ (? i) aaa /) {...} # зіставлення без урахування регістру
- (?: Pattern)
- (? Modifiers - modifiers: pattern)
-
Дозволяє групувати подвираженія регулярного виразу без запам'ятовування знайденого відповідності. Друга форма додатково включає або вимикає задані модифікатори . Наприклад, вираз
/ко(?:т|шка)/
- це короткий запис вираження/кот|кошка/
. - (? = Pattern)
- Відповідність з загляданням вперед без запам'ятовування знайденого відповідності. Наприклад, вираз
/Windows (?=95|98|NT|2000)/
відповідає "Windows" в рядку "Windows 98", але не відповідає в рядку "Windows 3.1". Після зіставлення пошук триває з позиції, наступної за знайденим відповідністю, без урахування заглядання вперед. - (?! Pattern)
- Невідповідність з загляданням вперед без запам'ятовування знайденого відповідності. Наприклад, вираз
/Windows (?!95|98|NT|2000)/
відповідає "Windows" в рядку "Windows 3.1", але не відповідає в рядку "Windows 98". Після зіставлення пошук триває з позиції, наступної за знайденим відповідністю, без урахування заглядання вперед. - (? <= Pattern)
- Відповідність з загляданням назад без запам'ятовування знайденого відповідності. Наприклад, вираз
/(?<=\t)\w+/
відповідає слову, наступного за символом табуляції, а також табуляцію не включається в $ &. Фрагмент, відповідний заглядання назад, повинен мати фіксовану ширину. - (? <! Pattern)
- Невідповідність з загляданням назад без запам'ятовування знайденого відповідності. Наприклад, вираз
/(?<!\t)\w+/
відповідає слову, перед яким немає символу табуляції. Фрагмент, відповідний заглядання назад, повинен мати фіксовану ширину.
6.4.6. Операції з регулярними виразами
До сих пір ми укладали регулярні вирази в символи //. Насправді символи-обмежувачі регулярного виразу визначаються q-операцією , яку ми до них застосовуємо. У цьому розділі докладно описані всі операції мови PERL з регулярними виразами.
6.4.6.1. Зіставлення зі зразком
Синтаксис: / pattern / modifiers m / pattern / modifiers
Ця операція зіставляє задану рядок зі зразком pattern і повертає істину або брехня в залежності від результату зіставлення. Зіставляється рядок задається лівим операндом операції = ~ або! ~, Наприклад:
$ Mynumber = '12345'; if ($ mynumber = ~ / ^ \ d + $ /) {# якщо рядок $ mynumber складається з десяткових цифр, то ... ... }
Якщо рядок не задана, то проводиться зіставлення з вмістом спеціальної змінної $ _. Зокрема, попередній приклад можна переписати так:
$ _ = '12345'; if (/ ^ \ d + $ /) { ... }
Крім стандартних, тут можна використовувати такі модифікатори:
модифікатор | опис |
---|---|
c | Чи не скидати позицію пошуку при невдалому зіставленні (тільки з модифікатором g). |
g | Глобальне зіставлення, т. Е. Пошук всіх входжень зразка. |
o | Компілювати регулярний вираз тільки один раз. |
Якщо регулярний вираз укладено в //, то початкове m необов'язково. Конструкція з початковим m дозволяє використовувати в якості обмежувачів регулярного виразу будь-які символи, допустимі в q-операціях. Корисні окремі випадки:
- Якщо обмежувачами є символи '', то інтерполяція рядка pattern не проводиться. В інших випадках відбувається інтерпретація зразка і якщо він містить змінні, то при кожному зіставленні проводиться його компіляція. Щоб уникнути цього, використовуйте модифікатор o (зрозуміло, якщо ви впевнені, що значення змінних, що входять в зразок, залишаються незмінними).
- Якщо обмежувачами є символи ?? , То застосовується правило єдиного зіставлення .
Якщо pattern є символом нового рядка, то замість нього використовується останнім успішно зіставлене регулярний вираз.
Якщо не заданий модифікатор g і результат зіставлення присвоюється списку, то при невдалому зіставленні повертається порожній список. Результат вдалого зіставлення залежить від наявності круглих дужок в зразку. Якщо їх немає, то повертається список (1). В іншому випадку повертається список, що складається з значень змінних $ 1, $ 2 і т. Д., Т. Е. Список всіх запам'ятали подстрок. наступний приклад
($ W1, $ w2, $ rest) = ($ x = ~ /^(\S+)\s+(\S+)\s*(.*)/);
заносить в змінну $ w1 перше слово рядка $ x, в змінну $ w2 її друге слово, а в змінну $ rest - залишок цього рядка.
Модифікатор g включає режим глобального зіставлення зі зразком, т. Е. Пошуку всіх відповідників в рядку. Його поведінка залежить від контексту. Якщо результат зіставлення присвоюється списку, то повертається список всіх запам'ятали подстрок. Якщо ж зразок не містить круглих дужок, то повертається список всіх відповідників зразком, як якби він був цілком укладений в круглі дужки. наступний приклад
$ _ = "12:23:45"; @result = / \ d + / g; foreach $ elem (@result) { print "$ elem \ n"; }
виведе на екран рядка 12, 23 і 45.
У скалярному контексті зіставлення з модифікатором g кожен раз шукає наступне відповідність зразком і повертає істину або брехня в залежності від результату пошуку. Позиція в рядку після останнього зіставлення може бути зчитана або змінена функцією pos (). Невдалий пошук зазвичай скидає позицію пошуку в нуль, але ми можемо уникнути цього, додавши модифікатор c. Зміна рядка також призводить до скидання позиції пошуку в ній.
Додаткові можливості надає метасимвол \ G, який має сенс тільки в поєднанні з модифікатором g. Цей метасимвол відповідає поточній позиції пошуку в рядку. Використання конструкції m / \ G ... / gc зручно, зокрема, для написання лексичних аналізаторів, що виконують різні дії для зустрінутих в уже згадуваному тексті лексем. наступний приклад
$ _ = 'Word1, word2, and 12345.'; LOOP: { print ( "number"), redo LOOP if /\G\d+\b[,.;]?\s*/gc; print ( "word"), redo LOOP if /\G[A-Za-z0-9]+\b[,.;]?\s*/gc; print ( "unknown"), redo LOOP if / \ G [^ A-Za-z0-9] + / gc; }
виведе на екран рядок word word word number.
6.4.6.2. Єдине зіставлення зі зразком
Синтаксис:? pattern? m? pattern?
Ця конструкція повністю аналогічна конструкції m / pattern / с єдиною відмінністю: успішне зіставлення зі зразком виконується тільки один раз між викликами функції reset () . Це зручно, наприклад, коли нам потрібно знайти тільки перше входження зразка в кожному файлі з проглядається набору, наприклад:
while (<>) { if (? ^ $?) { ... # Обробити перший пустий рядок файлу } } Continue { reset if eof; # Скинути статус ?? для наступного файлу }
6.4.6.3. Створення регулярного виразу
Синтаксис: qr / string / modifiers
Ця конструкція створює регулярний вираз з текстом string і модифікаторами modifiers і компілює його. Якщо обмежувачами є символи '', то інтерполяція рядка string не проводиться. В інших випадках відбувається інтерпретація зразка і якщо він містить змінні, то при кожному зіставленні проводиться його компіляція. Щоб уникнути цього, використовуйте модифікатор o (зрозуміло, якщо ви впевнені, що значення змінних, що входять в зразок, залишаються незмінними).
Одного разу створене регулярне вираз може вживатися як самостійно, так і в якості фрагмента інших регулярних виразів. приклади:
$ Re = qr / \ d + /; $ String = ~ / \ s * $ {re} \ s * /; # Включення в інше регулярний вираз $ String = ~ $ re; # Самостійне використання $ String = ~ / $ re /; # теж саме $ Re = qr / $ header / is; s / $ re / text /; # Те саме, що s / $ header / text / is
6.4.6.4. підстановка
Синтаксис: s / pattern / string / modifiers
Ця операція зіставляє задану рядок зі зразком pattern і замінює знайдені фрагменти на рядок string. Вона повертає кількість проведених замін або брехня (точніше, порожній рядок), якщо зіставлення закінчилося невдачею. Зіставляється рядок задається лівим операндом операції = ~ або! ~. Вона повинна бути скалярної змінної, елементом масиву або елементом асоціативного масиву, наприклад:
$ Path = '/ usr / bin / perl'; $ Path = ~ s | / usr / bin | / usr / local / bin |;
Якщо рядок не задана, то операція підстановки проводиться над спеціальної змінної $ _. Зокрема, попередній приклад можна переписати так:
$ _ = '/ Usr / bin / perl'; s | / usr / bin | / usr / local / bin |;
Крім стандартних, тут можна використовувати такі модифікатори:
модифікатор | опис |
---|---|
e | Обробляти string як вираз PERLа. |
g | Глобальна підстановка, т. Е. Заміна всіх входжень зразка. |
o | Компілювати регулярний вираз тільки один раз. |
Ми можемо використовувати замість // будь-який символ, допустимий в q-операціях. Якщо pattern укладений в парні дужки, то string повинен мати власну пару обмежувачів, наприклад s(foo)[bar]
або s<foo>/bar/
.
Якщо обмежувачами є символи '', то інтерполяція рядка pattern не проводиться. В інших випадках відбувається інтерпретація зразка і якщо він містить змінні, то при кожному зіставленні проводиться його компіляція. Щоб уникнути цього, використовуйте модифікатор o (зрозуміло, якщо ви впевнені, що значення змінних, що входять в зразок, залишаються незмінними).
Якщо pattern є символом нового рядка, то замість нього використовується останнім успішно зіставлене регулярний вираз.
За замовчуванням проводиться заміна тільки першого знайденого зразка. Щоб замінити всі входження зразка в рядку, потрібно використовувати модифікатор g.
Модифікатор e вказує, що string є виразом. В цьому випадку до string спочатку застосовується функція eval (), а потім проводиться підстановка. приклад:
$ _ = '123'; s / \ d + / $ & * 2 / e; # $ _ = '246' s / \ d / $ & * 2 / eg; # теж саме
Наведемо ще кілька типових прикладів використання операції підстановки. Видалення коментарів виду / * ... * / з тексту Java- або C-програми:
$ Program = ~ s { / \ * # Початок коментаря . *? # Мінімальна кількість символів \ * / # Кінець коментаря } [] Gsx;
Видалення початкових і кінцевих пробілів в рядку $ var:
for ($ var) { s / ^ \ s + //; s / \ s + $ //; }
Перестановка двох перших полів в $ _. Зверніть увагу, що в рядку заміни використовуються змінні $ 1 і $ 2, а не метасимволу \ 1 і \ 2:
s / ([^] *) * ([^] *) / $ 2 $ 1 /;
Заміна табуляцій на прогалини з вирівнюванням по колонках, кратним восьми:
1 while s / \ t + / '' x (length ($ &) * 8 - length ($ `)% 8) / e;
6.4.6.5. транслітерація
Синтаксис: tr / list1 / list2 / modifiers y / list1 / list2 / modifiers
Транслітерація полягає в заміні всіх символів зі списку list1 відповідними символами зі списку list2. Вона повертає кількість замінених або віддалених символів. Списки повинні складатися з окремих символів і / або діапазонів виду az. Преутворена рядок задається лівим операндом операції = ~ або! ~. Вона повинна бути скалярної змінної, елементом масиву або елементом асоціативного масиву, наприклад:
$ Test = 'ABCDEabcde'; $ Test = ~ tr / AZ / az /; # Заміна малих літер на прописні
Якщо рядок не задана, то операція підстановки проводиться над спеціальної змінної $ _. Зокрема, попередній приклад можна переписати так:
$ _ = 'ABCDEabcde'; tr / AZ / az /;
Ми можемо використовувати замість // будь-який символ, допустимий в q-операціях. Якщо list1 укладений в парні дужки, то list2 повинен мати власну пару обмежувачів, наприклад tr(AZ)[az]
або tr<AZ>/az/
.
Зазвичай ця операція називається tr. Синонім y введений для фанатиків редактора sed і використовується тільки ними. Транслітерація підтримує такі модифікатори:
модифікатор | опис |
---|---|
c | Замінювати символи, що не входять в list1. |
d | Видаляти символи, для яких немає заміни. |
s | Видаляти повторювані символи при заміні. |
U | Перетворювати в / з кодування UTF-8. |
C | Перетворювати в / з однобайтових кодування. |
Модифікатор c викликає транслітерацію всіх символів, що не входять в список list1.
Наприклад, операція tr/a-zA-Z/ /c
замінить всі символи, які не є латинськими літерами, на прогалини.
За замовчуванням, якщо list2 коротше, ніж list1, він доповнюється останнім своїм символом, а якщо він порожній, то приймається рівним list1 (це зручно для підрахунку кількості символів певного класу в рядку). Модифікатор d змінює ці правила: все символи з list1, яким немає відповідності в list2, видаляються з рядка. Наприклад, операція tr/a-zA-Z//cd
видалить з рядка всі символи, які не є латинськими буквами.
Модифікатор s видаляє повтори: якщо кілька символів поспіль замінилися на один і той же символ, то буде залишено тільки один екземпляр цього символу. Наприклад, операція tr/ / /s
видаляє в рядку повторювані пробіли.
Модифікатори C і U призначені для перекодування символів з системної кодування в UTF-8 і назад. Перший з них вказує на вихідну кодування, а другий - на кодування результату. Наприклад, tr/\0-\xFF//CU
перекодовує рядок з системної кодування в UTF-8, а tr/\0-\xFF//UC
виконає зворотну перекодування.
Транслітерація проводиться без інтерполяції списків символів, тому для використання в ній змінних необхідно викликати функцію eval (), наприклад:
eval "tr / $ oldlist / $ newlist /";
Коментарі
Коментуючи, пам'ятайте про те, що зміст і тон Вашого повідомлення можуть зачіпати почуття реальних людей, проявляйте повагу та толерантність до своїх співрозмовників навіть у тому випадку, якщо Ви не поділяєте їхню думку, Ваша поведінка за умов свободи висловлювань та анонімності, наданих інтернетом, змінює не тільки віртуальний, але й реальний світ. Всі коменти приховані з індексу, спам контролюється.