В этом базовом руководстве вы узнаете самые основы команды awk, а также увидите некоторые способы её использования при работе с текстом, включая вывод содержимого файла, а также его конкретных столбцов, строк и слов по указанным критериям. Приступим!

Что это за команда awk?


AWK – это скриптовый язык, который полезен при работе в командной строке и широко применяется для обработки текста.

При использовании awk вы можете выбирать данные – один или более отдельных фрагментов текста – на основе заданного критерия. Например, с помощью awk можно выполнять поиск конкретного слова или шаблона во фрагменте текста, а также выбирать определённую строку/столбец в файле.

Базовый синтаксис awk


Простейшая форма команды awk подразумевает описание основного действия в одинарных кавычках и фигурных скобках с указанием после него целевого файла.

Выглядеть она может так:

awk '{action}' your_file_name.txt

Когда вам нужно найти текст, соответствующий конкретному шаблону, или же конкретное слово в тексте, команда принимает следующий вид:

awk '/regex pattern/{action}' your_file_name.txt

Создание образца файла


Для создания файла в командной строке используется команда touch. Например: touch filename.txt, где filename – это произвольное имя файла.

Затем можно с помощью команды open (open filename.txt) запустить обработчик текста вроде TextEdit, который позволит внести в файл нужное содержимое.

Предположим, у вас есть текстовый файл information.txt, содержащий данные, разделённые по столбцам.

Выглядеть этот файл может так:

firstName       lastName        age     city       ID

Thomas          Shelby          30      Rio        400
Omega           Night           45      Ontario    600
Wood            Tinker          54      Lisbon     N/A
Giorgos         Georgiou        35      London     300
Timmy           Turner          32      Berlin     N/A

В приведённом примере мы видим по одному столбцу для
firstName, lastName, age, city и ID.

В любой момент можно просмотреть вывод содержимого вашего файла, выполнив cat text_file, где text_file представляет имя файла.

Вывод всего содержимого файла


Для вывода всего содержимого файла в качестве действия в фигурных скобках нужно указать print $0.

Сработает эта команда аналогично ранее упомянутой cat.

awk '{print $0}' information.txt

Вывод:

firstName       lastName        age     city       ID

Thomas          Shelby          30      Rio        400
Omega           Night           45      Ontario    600
Wood            Tinker          54      Lisbon     N/A
Giorgos         Georgiou        35      London     300
Timmy           Turner          32      Berlin     N/A

Если захотите добавить нумерацию строк, то нужно будет дополнить действие переменной NR:

awk '{print NR,$0}' information.txt


1 firstName     lastName        age     city       ID
2
3 Thomas        Shelby          30      Rio        400
4 Omega         Night           45      Ontario    600
5 Wood          Tinker          54      Lisbon     N/A
6 Giorgos       Georgiou        35      London     300
7 Timmy         Turner          32      Berlin     N/A

Вывод конкретных столбцов


При использовании awk можно указывать для вывода конкретные столбцы.

Вывод первого производится следующей командой:

awk '{print $1}' information.txt

Вывод:

Thomas
Omega
Wood
Giorgos
Timmy

Здесь $1 означает первое поле, то есть в данном случае первый столбец.

Для вывода второго столбца используется $2:

awk '{print $2}' information.txt

Вывод:

lastName

Shelby
Night
Tinker
Georgiou
Turner

По умолчанию начало и конец каждого столбца awk определяет по пробелу.

Для вывода большего числа столбцов, например, первого и четвёртого, нужно выполнить:

awk '{print $1, $4}' information.txt

Вывод:

firstName city
 
Thomas    Rio
Omega     Ontario
Wood      Lisbon
Giorgos   London
Timmy     Berlin

Здесь $1 представляет первое поле ввода (первый столбец), а $4 четвёртое. При этом они отделяются запятой, чтобы вывод разделялся пробелом и был более читаемым.

Для вывода последнего поля (последнего столбца) также можно использовать команду $NF, представляющую последнее поле записи:

awk '{print $NF}' information.txt

Вывод:

ID

400
600
N/A
300
N/A

Вывод конкретных строк столбца


Также можно указывать для вывода строку определённого столбца:

awk '{print $1}' information.txt | head -1

Вывод:

FirstName

Разделим эту команду на две части. Сначала awk '{print $1}' information.txt выводит первый столбец. Затем её результат (который мы видели выше) с помощью символа | передаётся на обработку команде head, где аргумент -1 указывает на выбор первой строки столбца.

Для вывода двух строк команда будет такой:

awk '{print $1}' information.txt | head -2

Вывод:

FirstName
Dionysia

Вывод строк с заданным шаблоном


Вы можете выводить строку, начинающуюся с заданной буквы. Например:

awk '/^O/' information.txt

Вывод:

Omega           Night           45      Ontario    600

Эта команда выбирает все строки с текстом, начинающимся на O.

Действие команды начинается с символа ^, который указывает на начало строки. После этого прописывается буква, с которой нужная вам строка должна начинаться.

По аналогичному принципу можно выводить строку, завершающуюся конкретным шаблоном:

awk '/0$/' information.txt

Вывод:

Thomas          Shelby          30      Rio        400
Omega           Night           45      Ontario    600
Giorgos         Georgiou        35      London     300

Эта команда выводит строки, оканчивающиеся на 0 – здесь с помощью символа $ мы указываем, как должна заканчиваться нужная строка.

При этом её можно несколько изменить:

awk '! /0$/' information.txt 

Символ ! используется в качестве приставки «НЕ», а значит, в этом случае будут выбраны строки, которые не оканчиваются на 0.

firstName       lastName        age     city       ID

Wood            Tinker          54      Lisbon     N/A
Timmy           Turner          32      Berlin     N/A

Использование регулярных выражений


Для вывода слов, содержащих определённые буквы, а также слов, соответствующих указанному шаблону, мы снова используем прямые слэши.

К примеру, если нас интересуют слова, содержащие io, мы пишем:

awk ' /io/{print $0}' information.txt

Вывод:

Thomas          Shelby          30      Rio        400
Omega           Night           45      Ontario    600
Giorgos         Georgiou        35      London     300

Мы получили строки, в которых содержатся слова, содержащие io.

Теперь предположим, что в файле есть дополнительный столбец department:

firstName       lastName        age     city       ID   department

Thomas          Shelby          30      Rio        400  IT
Omega           Night           45      Ontario    600  Design
Wood            Tinker          54      Lisbon     N/A  IT
Giorgos         Georgiou        35      London     300  Data
Timmy           Turner          32      Berlin     N/A  Engineering

Для поиска всей информации о людях, работающих в IT, нужно указать искомую строку между //:

awk '/IT/' information.txt

Вывод:

Thomas          Shelby          30      Rio        400  IT
Wood            Tinker          54      Lisbon     N/A  IT

А что, если мы хотим увидеть только имена и фамилии сотрудников из IT?

Тогда можно указать столбец так:

awk '/IT/{print $1, $2}' information.txt

Вывод:

Thomas Shelby
Wood   Tinker

В этом случае отобразятся только первый и второй столбцы строк, содержащих IT.

При поиске слов, содержащих конкретный шаблон, бывают случаи, когда требуется использовать экранирующий символ:

awk '/N\/A$/' information.txt

Вывод:

Wood            Tinker          54      Lisbon     N/A
Timmy           Turner          32      Berlin     N/A

Я хотела найти строки, оканчивающиеся на N/A. Поэтому при указании критериев поиска в ' // ', как это показывалось выше, мне пришлось использовать между N/A символ перехода \. В противном случае возникла бы ошибка.

Использование операторов сравнения


Если вы, предположим, захотите найти всю информацию о сотрудниках в возрасте до 40 лет, то нужно будет использовать оператор сравнения < так:

awk '$3 <  40 { print $0 }' information.txt

Вывод:

Thomas          Shelby          30      Rio        400
Giorgos         Georgiou        35      London     300
Timmy           Turner          32      Berlin     N/A

В выводе представлена информация о людях моложе 40.

Заключение


Вот и всё. Теперь у вас есть необходимая основа для начала работы с awk и управления текстовыми данными.

Благодарю за чтение и успехов вам в обучении!

Комментарии (12)


  1. dlinyj
    13.05.2022 12:56
    +6

    Моя производственная практика показала, что эти древние команды BASH используется очень часто. И умение эффективно использовать их выводит на новый уровень.
    И, как по мне, хоть уже тысячи раз говорили про всевозможные bash команды, освежить в памяти всегда полезно. Тем более что часто возвращаюсь к различным публикациям на хабре. Огромное спасибо за перевод!


    1. lrrr11
      13.05.2022 13:23
      +3

      строго говоря bash - это bash, а awk - это awk)


      1. dlinyj
        13.05.2022 14:53
        +1

        Согласен. Я в том ключе, что базовые команды.


  1. randomsimplenumber
    13.05.2022 18:42
    +1

    1. A1EF
      14.05.2022 01:04

      Тоже добавлю в копилочку неплохую шпаргалку: https://learnxinyminutes.com/docs/awk/


  1. pfemidi
    13.05.2022 21:54
    +4

    Дочитав до слов «символ перехода» я на некоторое время завис. Но продолжив чтение я понял что имеется в виду «escape character». Посмотрел оригинал и понял что я правильно предположил.


    1. Bright_Translate Автор
      14.05.2022 06:36
      +1

      Да, этот термин я неверно истолковал. Исправил.


  1. shovdmi
    14.05.2022 09:42
    +2

    Для создания файла в командной строке используется команда touch

    Формально говоря, утилита touch не для создания файла, а обновления его timestamp. То что она создает файл это её дополнительная фича. Ее может и не быть в системе, или могут отсутствовать права на ее запуск.

    man touch
    touch - change file timestamps

    создать можно перенаправлением вывода

    > newfile.txt


  1. orl1an1k
    14.05.2022 20:36
    +2

    Добавлю из своей практики полезные кейсы.

    Ключом -F можно указывать разделитель столбцов:

    awk -F '*' '{print $1}'

    Также полезно применять арифметические операторы к переменным. Вывод предпоследнего столбца:

    awk '{print $NF-1}'

    А также пару крутых однострочников которые показывают всю прелесть awk с другими команднами.

    Вывод потребления памяти с сортировкой из ps:

    ps axo rss,comm,pid | awk '{ proc_list[2] += $1; } END { for (proc in proc_list) { printf(1/=1024;printf "%.0fMB\t",$1}{print $2}'

    Потребление SWAP:

    for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | head




  1. maslyaev
    14.05.2022 23:02

    Таблички в текстовых файликах по колоночкам? Серьёзно? Почему хотя бы не csv или тот же jsonl?


    1. CtrlAltDragon
      15.05.2022 13:55
      +3

      Ну так awk, как и всё прочее — ориентирован на чтение глазами живым человеком, которому таблицы с колонками читать проще, чем JSON.

      Если бы в терминале ps печатал не такую таблицу:

      % ps
        PID TTY          TIME CMD
       1190 pts/5    00:00:00 ps
       8340 pts/5    00:00:01 zsh
      

      А вот такой страх и ужас:
      % ps | sed 's/^[ \t]*//g' | tr -s ' ' ',' | python -c 'import csv, json, sys; print(json.dumps([dict(r) for r in csv.DictReader(sys.stdin)]))' | jq | tee
      [
        {
          "PID": "2750",
          "TTY": "pts/5",
          "TIME": "00:00:00",
          "CMD": "ps"
        },
        {
          "PID": "2751",
          "TTY": "pts/5",
          "TIME": "00:00:00",
          "CMD": "sed"
        },
        {
          "PID": "2752",
          "TTY": "pts/5",
          "TIME": "00:00:00",
          "CMD": "tr"
        },
        {
          "PID": "2753",
          "TTY": "pts/5",
          "TIME": "00:00:00",
          "CMD": "python"
        },
        {
          "PID": "2754",
          "TTY": "pts/5",
          "TIME": "00:00:00",
          "CMD": "jq"
        },
        {
          "PID": "8340",
          "TTY": "pts/5",
          "TIME": "00:00:02",
          "CMD": "zsh"
        }
      ]
      

      то ни о каких FreeBSD, Linux и прочих Unix-like системах мы бы сейчас и не слышали.


    1. randomsimplenumber
      15.05.2022 20:13
      -1

      Почему хотя бы не csv или тот же jsonl?

      Выхлоп почти любой команды достаточно просто преобразовать в вид, понятный awk. А вот преобразовать произвольный текст в json не всегда просто.