summaryrefslogtreecommitdiffhomepage
path: root/uk-ua/awk-uk.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'uk-ua/awk-uk.html.markdown')
-rw-r--r--uk-ua/awk-uk.html.markdown397
1 files changed, 397 insertions, 0 deletions
diff --git a/uk-ua/awk-uk.html.markdown b/uk-ua/awk-uk.html.markdown
new file mode 100644
index 00000000..a99dca17
--- /dev/null
+++ b/uk-ua/awk-uk.html.markdown
@@ -0,0 +1,397 @@
+---
+category: tool
+tool: awk
+filename: learnawk-ua.awk
+contributors:
+ - ["Marshall Mason", "http://github.com/marshallmason"]
+translators:
+ - ["Ihor Sokorchuk", "https://github.com/IhorSokorchuk"]
+lang: uk-ua
+---
+
+AWK є стандартним інструментом у кожній POSIX-сумісній системі UNIX.
+Він схожий на flex/lex із командного рядка й чудово підходить для завдань
+обробки тексту та інших скриптових задач. Він має подібний до C синтаксис,
+але без обов’язкових крапок з комою (хоча їх все одно потрібно використовувати,
+якщо ви пишете однорядковий код, для якого AWK відмінно підходить),
+у ньому немає ручного керування пам’яттю та статичної типізації.
+Він відмінно обробляє текст. Ви можете викликати його зі сценарію оболонки або
+використовувати як окрему мову сценаріїв.
+
+Навіщо використовувати AWK замість Perl? Це читабельність коду.
+Адже AWK легше читати, ніж Perl. Для простих сценаріїв обробки тексту,
+особливо тих, які читають файли рядок за рядком і розбивають їх
+за роздільниками, AWK є чи не найкращим інструментом.
+
+```awk
+#!/usr/bin/awk -f
+
+# Коментарі у AWK схожі на цей коментар.
+
+# Програми AWK складаються з набору шаблонів і дій.
+pattern1 { action; } # зовсім як lex
+pattern2 { action; }
+
+# Скрипт виконує неявний цикл, у якому AWK автоматично читає та аналізує кожен
+# запис із кожного наданого йому файла. Кожен такий запис розділяється на поля
+# роздільником FS, який за замовчуванням має значення пробіл (кілька пробілів
+# або символів табуляції вважаються одним роздільником).
+# Можна встановити значення FS в командному рядку (-FC) або у шаблоні BEGIN.
+
+# Одним із спеціальних шаблонів є шаблон BEGIN. Цей шаблон є дійсним
+# ДО прочитання будь-якого з вхідних файлів.
+# Ще один спеціальний шаблон END є дійсним після кінця останнього з вказаних
+# вхідних файлів, або після стандартного введення, якщо вхідні файли не вказано.
+# Також використовується роздільник між полями виводу (OFS), значення якого
+# ви також можете призначити, і для якого за замовчуванням встановлено
+# значення один пробіл.
+
+
+BEGIN {
+
+ # BEGIN запускатиметься на початку програми. Тут розміщують весь код
+ # попереднього налаштування перед обробкою будь-яких текстових файлів.
+ # Якщо ваш скрипт не читає текстові файли, розглядайте BEGIN як
+ # головну точку входу.
+
+ # Змінні є глобальними. Просто встановіть їх і використовуйте.
+ # Оголошувати змінні не потрібно.
+ count = 0;
+
+ # Оператори є такими ж як у мові C та схожих на неї мовах програмування.
+ a = count + 1;
+ b = count - 1;
+ c = count * 1;
+ d = count / 1; # цілочислене ділення
+ e = count % 1; # модуль
+ f = count ^ 1; # піднесення до степеня
+
+ a += 1;
+ b -= 1;
+ c *= 1;
+ d /= 1;
+ e %= 1;
+ f ^= 1;
+
+ # Постфіксний оператор збільшення та зменшення на одиницю
+ a++;
+ b--;
+
+ # Префіксний оператор, який повертає збільшене на одиницю значення
+ ++a;
+ --b;
+
+ # Зверніть також увагу, що в кінці рядка не обов'язково вказувати
+ # розділовий знак крапка з комою.
+
+ # Оператор галудження
+ if (count == 0)
+ print "Starting with count of 0";
+ else
+ print "Huh?";
+
+ # Можна використовувати тернарний оператор
+ print (count == 0) ? "Starting with count of 0" : "Huh?";
+
+ # Для блоків, що складаються з кількох рядків, використовують дужки
+ while (a < 10) {
+ print "String concatenation is done" " with a series" " of"
+ " space-separated strings";
+ print a;
+
+ a++;
+ }
+
+ for (i = 0; i < 10; i++)
+ print "Good ol' for loop";
+
+ # Порівняння є стандартними:
+ # a < b # менше ніж
+ # a <= b # менше або дорівнює
+ # a != b # не дорівнює
+ # a == b # дорівнює
+ # a > b # більше ніж
+ # a >= b # більше або дорівнює
+
+ # Логічні оператори також стандартні:
+ # a && b # AND - І
+ # a || b # OR - АБО
+
+ # Крім того, є перевірка на збіг із регулярним виразом:
+ if ("foo" ~ "^fo+$")
+ print "Fooey!";
+ if ("boo" !~ "^fo+$")
+ print "Boo!";
+
+ # Масиви:
+ arr[0] = "foo";
+ arr[1] = "bar";
+
+ # Також можна ініціалізувати масив за допомогою вбудованої функції split():
+ n = split("foo:bar:baz", arr, ":");
+
+ # Підтримуються асоціативні масиви (насправді, всі масиви асоціативні):
+ assoc["foo"] = "bar";
+ assoc["bar"] = "baz";
+
+ # Та багатовимірні масиви (з деякими обмеженнями, які описуються далі):
+ multidim[0,0] = "foo";
+ multidim[0,1] = "bar";
+ multidim[1,0] = "baz";
+ multidim[1,1] = "boo";
+
+ # Можна перевірити членство в масиві:
+ if ("foo" in assoc)
+ print "Fooey!";
+
+ # Оператор 'in' також можна використовувати для обходу ключів масиву:
+ for (key in assoc)
+ print assoc[key];
+
+ # Командний рядок знаходиться у спеціальному масиві з ім'ям ARGV
+ for (argnum in ARGV)
+ print ARGV[argnum];
+
+ # Можна видаляти елементи масиву. Це особливо корисно для того, щоб AWK
+ # не розглядав аргументи як імена файлів для обробки
+ delete ARGV[1];
+
+ # Кількість аргументів командного рядка міститься у змінній з іменем ARGC
+ print ARGC;
+
+ # AWK має багато вбудованих функцій. Вони діляться на три категорії, які
+ # буде розглянуто далі.
+
+ return_value = arithmetic_functions(a, b, c);
+ string_functions();
+ io_functions();
+}
+
+# Функції декларуються так:
+function arithmetic_functions(a, b, c, d) {
+
+ # Однією з дратівливих особливостей AWK є те, що в цій мові немає
+ # локальних змінних. Усе є глобальним.
+ # Для коротких сценаріїв це добре, навіть корисно, але для довших
+ # сценаріїв це може бути проблемою.
+
+ # Проте, є обхідний шлях (huk). Вказані у функції аргументи є локальними
+ # у функції. Крім того, AWK дозволяє вказувати більше аргументів функції,
+ # ніж потрібно. Тому, просто вставте локальну змінну в оголошення
+ # функції, як це зроблено вище. Можна додати також додаткові пробіли,
+ # щоб відрізнити фактичні параметри функції від створених у такий спосіб
+ # локальних змінних.
+ # У наведеному вище прикладі, змінні a, b, c є фактичними параметрами,
+ # тоді як d є лише локальною змінною.
+
+ # Тепер, розглянемо математичні функції
+
+ # Більшість реалізацій AWK підтримують стандартні тригонометричні функції:
+ localvar = sin(a);
+ localvar = cos(a);
+ localvar = atan2(b, a); # арктангенс b / a
+
+ # та логаритмічні обчислення:
+ localvar = exp(a);
+ localvar = log(a);
+
+ # квадратний корінь:
+ localvar = sqrt(a);
+
+ # округлення до цілого числа:
+ localvar = int(5.34); # localvar => 5
+
+ # випадкові числа:
+ srand(); # встановити т.зв. "сіль" (без аргумента використовується час)
+ localvar = rand(); # випадкове число від 0 до 1.
+
+ # Повернути значення можна так:
+ return localvar;
+}
+
+# Функції для обробки рядків тексту
+function string_functions( localvar, arr) {
+
+ # AWK, як мова обробки тексту, підтримує функції для обробки рядків.
+ # У багатьох з цих функцій використовуються регулярні вирази.
+
+ # Пошук і заміна, першої (sub) або всіх відповідностей (gsub).
+ # Обидві вони повертають кількість замінених відповідностей.
+ localvar = "fooooobar";
+ sub("fo+", "Meet me at the ", localvar); # localvar => "Meet me at the bar"
+ gsub("e", ".", localvar); # localvar => "m..t m. at th. bar"
+
+ # Пошук підрядка, який збігається з регулярним виразом:
+ # index() робить те ж саме, але не використовує регулярний вираз.
+ match(localvar, "t"); # => 4, оскільки 't' є четвертим символом
+
+ # Розбити рядок за роздільником
+ n = split("foo-bar-baz", arr, "-"); # a[1] = "foo"; a[2] = "bar"; a[3] = "baz"; n = 3
+
+ # Інші корисні речі
+ sprintf("%s %d %d %d", "Testing", 1, 2, 3); # => "Testing 1 2 3"
+ substr("foobar", 2, 3); # => "oob"
+ substr("foobar", 4); # => "bar"
+ length("foo"); # => 3
+ tolower("FOO"); # => "foo"
+ toupper("foo"); # => "FOO"
+}
+
+# Функції введення-виведення
+function io_functions( localvar) {
+
+ # Ви вже бачили print
+ print "Hello world";
+
+ # Є також printf
+ printf("%s %d %d %d\n", "Testing", 1, 2, 3);
+
+ # AWK сам по собі не має дескрипторів файлів. Він автоматично відкриває
+ # дескриптор файлу, коли виконується дія, яка потребує дискриптора.
+ # Рядок, який використано для цього, можна розглядати як дескриптор файлу
+ # для введення-виводу. Це схоже на сценарії оболонки.
+ # Рядок, при цьому, повинен точно збігатися. Тому використовуйте змінну:
+ outfile = "/tmp/foobar.txt";
+ print "foobar" > outfile;
+
+ # Тепер, рядок вихідного файлу є дескриптором файлу.
+ # Ви можете закрити його:
+ close(outfile);
+
+ # Ось як запустити команду в оболонці
+ system("echo foobar"); # => друкує foobar
+
+ # Читає рядок із потоку стандартного введення та зберігає в localvar
+ getline localvar;
+
+ # Читає рядок з каналу (використовуйте рядок, щоб правильно його закрити)
+ cmd = "echo foobar";
+ cmd | getline localvar; # localvar => "foobar"
+ close(cmd);
+
+ # Читає рядок з файлу та зберігає в localvar
+ infile = "/tmp/foobar.txt";
+ getline localvar < infile;
+ close(infile);
+}
+
+# Як вже вказувалося, програми AWK складаються з набору шаблонів та дій.
+# Було розглянуто шаблони BEGIN та END . Інші шаблони використовуються тоді,
+# коли скрипт обробляє рядки з файлів або стандартного потоку введення.
+#
+
+# Вказані у командному рядку аргументи розглядаються як імена файлів для
+# обробки. Усі ці файли обробляються послідовно один за одним.
+# Виконується неявний цикл, в якому обробляються усі рядки з цих файлів.
+# Шаблони та дії AWK схожі на оператор switch всередині циклу.
+
+/^fo+bar$/ {
+ # Ця дія буде виконуватися для кожного рядка, який збігається з регулярним
+ # виразом: /^fo+bar$/, і буде пропущена для усіх рядків,
+ # які не збігаються з ним. Давайте просто надрукуємо рядок:
+
+ print;
+
+ # Без аргументів! Це тому, що print має аргумент за замовчуванням: $0.
+ # $0 - ім'я змінної, яка містить увесь поточний рядок. Ця змінна
+ # створюється автоматично.
+
+ # Також існують інші змінні зі знаком $. Кожен рядок неявно розбивається
+ # перед викликом кожної дії так, як це робить оболонка. І так само, як і
+ # в оболонці, до кожного поля можна отримати доступ із відповідної змінної
+ # зі знаком долара.
+
+ # Тут буде виведене друге та четверте поля з рядка
+ print $2, $4;
+
+ # AWK автоматично визначає багато інших змінних, щоб допомогти перевірити
+ # та обробити кожен рядок. Однією з них є NF.
+
+ # Друкує кількість полів у цьому рядку
+ print NF;
+
+ # Друк останнього поля у цьому рядку
+ print $NF;
+}
+
+# Кожен шаблон є логічним виразом. Регулярний вираз у наведеному шаблоні
+# також є перевіркою на істине/хибне, але частина виразу прихована.
+# Шаблон обробляє кожен вхідний рядок і його повна версія є такою:
+$0 ~ /^fo+bar$/ {
+ print "Equivalent to the last pattern";
+}
+
+a > 0 {
+ # цей блок виконуватиметься для кожного рядка, допоки змінна a буде
+ # більшою від 0
+}
+
+# Ідея AWK зрозуміла. Обробка текстових файлів, порядкове зчитування і
+# обробка, зокрема розбиття за роздільником, настільки поширені в UNIX,
+# що AWK — це мова сценаріїв, яка виконує все це сама, без ваших вказівок.
+# Все, що вам потрібно зробити, це написати шаблони та дії на основі того,
+# що ви очікуєте від введення, і що ви хочете з ним зробити.
+
+# Ось короткий приклад простого сценарію, для якого чудово підходить AWK.
+# Цей сценарій прочитає ім’я зі стандартного потоку введення, а потім надрукує
+# середній вік для людей з цим іменем.
+# Нехай, як аргумент скрипта вказано ім’я файла з такими даними:
+#
+# Bob Jones 32
+# Jane Doe 22
+# Steve Stevens 83
+# Bob Smith 29
+# Bob Barker 72
+#
+
+# Ось сценарій:
+
+BEGIN {
+
+ # Спершу попросимо користувача ввести ім'я
+ print "What name would you like the average age for?";
+
+ # Отримати рядок зі стандартного потоку введення, а не з файлів
+ # командного рядка
+ getline name < "/dev/stdin";
+}
+
+# Тепер обробимо кожен рядок, першим полем якого є вказане ім'я
+$1 == name {
+
+ # Тут усередині ми маємо доступ до низки корисних змінних, які вже
+ # встановлені для нас попередньо:
+ # $0 - це весь рядок
+ # $3 - це третє поле, вік, який нас тут цікавить
+ # NF - це кількість полів, яка має бути 3
+ # NR - це кількість записів (рядків), переглянутих на поточний момент
+ # FILENAME - ім'я файла, який обробляється
+ # FS - це роздільник полів, який використовується. Тут це - " "
+ # ... є багато інших задокументованих на сторінці керівництва змінних
+
+ # Обчислимо поточну суму та кількість рядків, які відповідають шаблону
+ sum += $3;
+ nlines++;
+}
+
+# Ще один спеціальний шаблон називається END. Він виконується після обробки
+# всіх текстових файлів. На відміну від BEGIN, він запуститься, якщо були
+# дані для обробки. Він виконуватиметься після того, як будуть прочитані та
+# оброблені, відповідно до вказаних правил та дій, усі файли з вхідними даними.
+# Його мета зазвичай полягає в тому, щоб вивести якийсь остаточний звіт або
+# зробити щось із накопиченою протягом сценарію сукупністю даних
+
+END {
+ if (nlines)
+ print "The average age for " name " is " sum / nlines;
+}
+```
+
+Детальніше дивіться:
+
+* [Awk tutorial](http://www.grymoire.com/Unix/Awk.html)
+* [Awk man page](https://linux.die.net/man/1/awk)
+* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html) GNU Awk is found on most Linux systems.
+* [AWK one-liner collection](http://tuxgraphics.org/~guido/scripts/awk-one-liner.html)
+* [Awk alpinelinux wiki](https://wiki.alpinelinux.org/wiki/Awk) a technical summary and list of "gotchas" (places where different implementations may behave in different or unexpected ways).
+* [basic libraries for awk](https://github.com/dubiousjim/awkenough)