Ос

Основи у AWK

1 вправа

Про концепцію Основи

Далі ми називатимемо мову AWK, а виконуваний файл, що інтерпретує програми AWK, - awk або gawk.

Шаблони та дії

Програма AWK складається з пар «шаблон-дія»

pattern1 { action1 }
pattern2 { action2 }
...

Шаблон може бути регулярним виразом, який зіставляється з вхідними даними. Він також може бути будь-яким виразом, результатом якого є правда або неправда.

Дія - це одна або кілька команд AWK. Фігурні дужки навколо неї обовʼязкові.

Якщо результат шаблону - правда, то виконується відповідна дія.

Записи та поля

AWK розбирає вхідні дані як послідовність записів. Кожен запис розбивається на нуль або більше полів.

Типова поведінка така:

  • розбивати вхідні дані на записи, використовуючи символ нового рядка як «розділювач записів», тож кожен рядок - це запис.
  • розбивати запис на поля, використовуючи пробільні символи як «розділювач полів», тож кожне слово - це поле.

Шаблони та дії (продовження)

Шаблон можна опустити, і тоді дія виконується для кожного вхідного запису.

Дію можна опустити, і тоді типовою дією буде вивести поточний запис.

Спеціальні шаблони

Є два спеціальні шаблони, які використовуються найчастіше.

  • BEGIN виконує повʼязану з ним дію, перш ніж буде прочитано хоч якісь вхідні дані.
  • END виконує повʼязану з ним дію після того, як усі вхідні дані прочитано.

Змінні полів

Поля позначаються як $1, $2, $3 тощо.

Поточний запис - $0.

Caution

Уточнімо: це не зовсім «змінні». Символ $ можна вважати оператором, який повертає значення поля із заданим номером. Глибше ми розглянемо це в наступних концепціях.

Ось кілька інших вбудованих змінних, які часто використовуються.

Вбудовані змінні, що керують розбором вхідних даних

  • RS - це розділювач записів у вхідних даних. Як уже згадувалося, його типове значення - символ нового рядка.
  • FS - це розділювач полів у вхідних даних.

Ці змінні часто задають у блоці дій BEGIN.

Вбудовані змінні, що несуть інформацію

Ці змінні AWK встановлює автоматично під час виконання програми.

  • NF зберігає кількість полів у поточному записі.
    • Щоб отримати значення останнього поля, скористайтеся $NF.
  • NR зберігає номер поточного запису.
    • Коли обробляється кілька вхідних файлів, NR містить загальну кількість уже оброблених записів.
  • FNR зберігає номер поточного запису в поточному вхідному файлі.
    • Щоб показати різницю між NR і FNR, ось поширений прийом в AWK.
      NR == FNR {action}
      
      Це означає «якщо накопичений номер запису дорівнює номеру запису в поточному файлі». Це справджується лише для записів у першому вхідному файлі.

Правдивість

AWK використовує те саме поняття правдивості, що й C:

  • Число 0 - неправда.
  • Будь-яке інше число - правда.

Оскільки AWK - мова обробки тексту, поняття правди поширюється й на рядки тексту (англ. string).

  • Порожній рядок тексту "" - неправда.
  • Будь-який непорожній рядок тексту - правда.
Note

AWK використовує те саме поняття правдивості, що й C

AWK виник у Bell Labs у 1970-х роках, у тому самому середовищі, де винайшли C. Мова C значно вплинула на синтаксис AWK.

Caution

Одна особливість, за якою варто стежити

  • Число 0 - неправда.
  • Непорожній рядок тексту "0" - правда!

Докладніше про типи даних в AWK поговоримо в наступних концепціях.

Коментарі

Коментарі починаються із символу # і тривають до кінця рядка.

Як передати вхідні дані до awk

awk може читати вхідні дані з файлів або зі стандартного введення. Спрацює будь-який із цих способів.

awk '/regex/ {print $1}' file1 file2 ...

awk '/regex/ {print $1}' < file

some_command_here | awk '/regex/ {print $1}'

Приклади

У Unix-подібних системах файл /etc/passwd містить інформацію про користувачів. Кожен користувач описаний в окремому рядку, а поля розділені двокрапками.

Щоб вивести список імен користувачів:

awk '
    BEGIN { FS = ":" }
    { print $1 }
' /etc/passwd

Зауважмо, що дія {print $1} не має шаблону, тому виконується для кожного запису.

Якщо ми хочемо обмежити виведення лише користувачами, які використовують bash як свою оболонку входу, можна зробити так:

awk '
    BEGIN { FS = ":" }
    $7 == "/bin/bash" { print $1 }
' /etc/passwd

Ще кілька прикладів

Ось кілька програм awk, які дають ті самі результати, що й інші поширені команди Unix.

  • Вивести вміст файлу

    cat file.txt
    
    awk '1' file.txt
    
  • Пошук шаблонів у файлі

    grep 'foo.*bar' file.txt
    
    awk '/foo.*bar/' file.txt
    
  • Вивести лише кілька перших рядків файлу

    head -n 20 file.txt
    
    awk '
        1
        NR == 20 {exit}
    ' file.txt
    
  • Замінити текст у файлі

    sed 's/foo/bar/' file.txt
    
    awk '{sub(/foo/, "bar")};1' file.txt
    # or more readably
    awk '
        {
            sub(/foo/, "bar")
            print
        }
    ' file.txt
    
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Основи