Как использовать команду awk в Linux
В Linux awk
— это динамо-машина для работы с текстом из командной строки, а также мощный язык сценариев. Вот введение в некоторые из его самых крутых функций.
Как awk получил свое название
Команда awk
была названа с использованием инициалов трех человек, написавших исходную версию в 1977 году: Альфреда Ахо, Питера Вайнбергера и Брайана Кернигана. Эти трое принадлежали к легендарному пантеону UNIX компании AT&T Bell Laboratories. Благодаря вкладу многих других, с тех пор awk
продолжает развиваться.
Это полноценный язык сценариев, а также полный набор инструментов для работы с текстом в командной строке. Если эта статья разожжет ваш аппетит, вы можете ознакомиться со всеми подробностями о awk
и его функциях.
Правила, шаблоны и действия
awk
работает с программами, которые содержат правила, состоящие из шаблонов и действий. Действие выполняется над текстом, соответствующим шаблону. Шаблоны заключаются в фигурные скобки ({}
). Вместе шаблон и действие образуют правило. Вся программа awk
заключена в одинарные кавычки ().
Давайте взглянем на самый простой тип программы awk
. У него нет шаблона, поэтому он соответствует каждой строке введенного в него текста. Это означает, что действие выполняется в каждой строке. Мы будем использовать его в выводе команды who
.
Вот стандартный вывод who
:
who
Возможно, нам не нужна вся эта информация, мы просто хотим видеть имена в учетных записях. Мы можем направить вывод who
в awk
, а затем указать awk
напечатать только первое поле.
По умолчанию awk
считает поле строкой символов, окруженной пробелом, началом строки или концом строки. Поля обозначаются знаком доллара ($
) и числом. Таким образом, $1
представляет собой первое поле, которое мы будем использовать с действием print
для печати первого поля.
Набираем следующее:
who | awk '{print $1}'
awk
печатает первое поле и отбрасывает остальную часть строки.
Мы можем напечатать столько полей, сколько захотим. Если мы добавим запятую в качестве разделителя, awk
напечатает пробел между каждым полем.
Мы вводим следующее, чтобы также напечатать время, когда человек вошел в систему (четвертое поле):
who | awk '{print $1,$4}'
Есть пара специальных идентификаторов полей. Они представляют всю строку текста и последнее поле в строке текста:
- $0: представляет всю строку текста.
- $1: представляет первое поле.
- $2: представляет второе поле.
- $7: представляет седьмое поле.
- $45: представляет 45-е поле.
- $NF: обозначает количество полей и представляет последнее поле.
Мы напечатаем следующее, чтобы открыть небольшой текстовый файл, содержащий короткую цитату, приписываемую Деннису Ритчи:
cat dennis_ritchie.txt
Мы хотим, чтобы awk
печатал первое, второе и последнее поле цитаты. Обратите внимание, что несмотря на то, что он обёрнут в окне терминала, это всего лишь одна строка текста.
Набираем следующую команду:
awk '{print $1,$2,$NF}' dennis_ritchie.txt
Мы не знаем этой «простоты». является 18-м полем в строке текста, и нам все равно. Что мы знаем, так это то, что это последнее поле, и мы можем использовать $NF
, чтобы получить его значение. Точка просто считается другим символом в теле поля.
Добавление разделителей полей вывода
Вы также можете указать awk
печатать определенный символ между полями вместо символа пробела по умолчанию. Вывод по умолчанию команды date
несколько необычен, потому что время вставляется прямо в его середину. Однако мы можем ввести следующее и использовать awk
для извлечения нужных полей:
date
date | awk '{print $2,$3,$6}'
Мы будем использовать переменную OFS
(разделитель полей вывода), чтобы поместить разделитель между месяцем, днем и годом. Обратите внимание, что ниже мы заключаем команду в одинарные кавычки (), а не в фигурные скобки (
{}
):
date | awk 'OFS="/" {print$2,$3,$6}'
date | awk 'OFS="-" {print$2,$3,$6}'
Правила НАЧАЛА и КОНЦА
Правило BEGIN
выполняется один раз перед началом любой обработки текста. Фактически, он выполняется еще до того, как awk
прочтет какой-либо текст. Правило END
выполняется после завершения всей обработки. У вас может быть несколько правил BEGIN
и END
, и они будут выполняться по порядку.
В нашем примере правила BEGIN
мы напечатаем всю цитату из файла dennis_ritchie.txt
, который мы использовали ранее, с заголовком над ней.
Для этого мы набираем эту команду:
awk 'BEGIN {print "Dennis Ritchie"} {print $0}' dennis_ritchie.txt
Обратите внимание, что правило BEGIN
имеет собственный набор действий, заключенных в собственный набор фигурных скобок ({}
).
Мы можем использовать тот же метод с командой, которую мы использовали ранее, для передачи вывода из who
в awk
. Для этого набираем следующее:
who | awk 'BEGIN {print "Active Sessions"} {print $1,$4}'
Разделители полей ввода
Если вы хотите, чтобы awk
работал с текстом, в котором не используются пробелы для разделения полей, вы должны сообщить ему, какой символ текст использует в качестве разделителя полей. Например, в файле /etc/passwd
для разделения полей используется двоеточие (:
).
Мы будем использовать этот файл и параметр -F
(строка-разделитель), чтобы указать awk
использовать двоеточие (:
) в качестве разделителя. Мы вводим следующее, чтобы указать awk
распечатать имя учетной записи пользователя и домашнюю папку:
awk -F: '{print $1,$6}' /etc/passwd
Выходные данные содержат имя учетной записи пользователя (или имя приложения или демона) и домашнюю папку (или расположение приложения).
Добавление узоров
Если все, что нас интересует, это учетные записи обычных пользователей, мы можем включить шаблон с нашим действием печати, чтобы отфильтровать все остальные записи. Поскольку число идентификаторов пользователей больше или равно 1000, мы можем основывать наш фильтр на этой информации.
Мы вводим следующее, чтобы выполнить наше действие печати только тогда, когда третье поле ($3
) содержит значение 1000 или больше:
awk -F: '$3 >= 1000 {print $1,$6}' /etc/passwd
Шаблон должен непосредственно предшествовать действию, с которым он связан.
Мы можем использовать правило BEGIN
, чтобы указать заголовок для нашего небольшого отчета. Мы вводим следующее, используя нотацию (\n
), чтобы вставить символ новой строки в строку заголовка:
awk -F: 'BEGIN {print "User Accounts\n-------------"} $3 >= 1000 {print $1,$6}' /etc/passwd
Шаблоны — это полноценные регулярные выражения, и они — одно из достоинств awk
.
Допустим, мы хотим увидеть универсальные уникальные идентификаторы (UUID) смонтированных файловых систем. Если мы ищем в файле /etc/fstab
вхождения строки «UUID», он должен вернуть нам эту информацию.
Мы используем шаблон поиска «/UUID/» в нашей команде:
awk '/UUID/ {print $0}' /etc/fstab
Он находит все вхождения «UUID» и печатает эти строки. На самом деле мы получили бы тот же результат без действия print
, потому что действие по умолчанию печатает всю строку текста. Однако для ясности часто полезно быть явным. Когда вы просматриваете сценарий или свой файл истории, вы будете рады, что оставили подсказки для себя.
Первая найденная строка была строкой комментария, и хотя строка «UUID» находится в середине, awk
все же нашел ее. Мы можем настроить регулярное выражение и указать awk
обрабатывать только строки, начинающиеся с «UUID». Для этого мы вводим следующее, которое включает токен начала строки (^
):
awk '/^UUID/ {print $0}' /etc/fstab
Так-то лучше! Теперь мы видим только подлинные инструкции по монтированию. Чтобы еще больше уточнить вывод, мы вводим следующее и ограничиваем отображение первым полем:
awk '/^UUID/ {print $1}' /etc/fstab
Если бы на этой машине было смонтировано несколько файловых систем, мы бы получили аккуратную таблицу их UUID.
Встроенные функции
В awk
есть множество функций, которые вы можете вызывать и использовать в своих программах как из командной строки, так и в сценариях. Если вы немного покопаетесь, вы обнаружите, что это очень плодотворно.
Чтобы продемонстрировать общую технику вызова функции, мы рассмотрим некоторые числовые. Например, следующий код выводит квадратный корень из 625:
awk 'BEGIN { print sqrt(625)}'
Эта команда печатает арктангенс 0 (ноль) и -1 (который оказывается математической константой пи):
awk 'BEGIN {print atan2(0, -1)}'
В следующей команде мы изменяем результат функции atan2()
перед его печатью:
awk 'BEGIN {print atan2(0, -1)*100}'
Функции могут принимать выражения в качестве параметров. Например, вот замысловатый способ получить квадратный корень из 25:
awk 'BEGIN { print sqrt((2+3)*5)}'
awk-скрипты
Если ваша командная строка усложняется или вы разрабатываете подпрограмму, которую, как вы знаете, вы захотите использовать снова, вы можете перенести свою команду awk
в скрипт.
В нашем примере скрипта мы собираемся сделать все следующее:
- Сообщите оболочке, какой исполняемый файл использовать для запуска скрипта.
- Подготовьте
awk
для использования переменной-разделителя полейFS
для чтения входного текста с полями, разделенными двоеточиями (:
). - Используйте разделитель выходных полей
OFS
, чтобы указатьawk
использовать двоеточие (:
) для разделения полей в выходных данных. - Установите счетчик на 0 (ноль).
- Установите во втором поле каждой строки текста пустое значение (это всегда x, поэтому нам не нужно его видеть).
- Выведите строку с измененным вторым полем.
- Увеличить счетчик.
- Выведите значение счетчика.
Наш скрипт показан ниже.
Правило BEGIN
выполняет подготовительные шаги, а правило END
отображает значение счетчика. Среднее правило (у которого нет ни имени, ни шаблона, поэтому оно соответствует каждой строке) изменяет второе поле, печатает строку и увеличивает счетчик.
Первая строка скрипта сообщает оболочке, какой исполняемый файл использовать (в нашем примере awk
) для запуска скрипта. Он также передает параметр -f
(имя файла) в awk
, который сообщает ему, что текст, который он будет обрабатывать, будет получен из файла. Мы передадим имя файла сценарию при его запуске.
Мы включили сценарий ниже в виде текста, чтобы вы могли вырезать и вставлять:
#!/usr/bin/awk -f BEGIN { # set the input and output field separators FS=":" OFS=":" # zero the accounts counter accounts=0 } { # set field 2 to nothing $2="" # print the entire line print $0 # count another account accounts++ } END { # print the results print accounts " accounts.\n" }
Сохраните это в файле с именем omit.awk
. Чтобы сделать скрипт исполняемым, мы вводим следующее с помощью chmod
:
chmod +x omit.awk
Теперь мы запустим его и передадим скрипту файл /etc/passwd
. Это файл , который awk
обработает для нас, используя правила внутри скрипта:
./omit.awk /etc/passwd
Файл обрабатывается, и каждая строка отображается, как показано ниже.
Записи «x» во втором поле были удалены, но обратите внимание, что разделители полей все еще присутствуют. Строки подсчитываются, и общее количество дается внизу вывода.
awk не означает неловкость
awk
не означает «неуклюжий»; это означает элегантность. Его описывают как фильтр обработки и генератор отчетов. Точнее, это и то, и другое, или, точнее, инструмент, который вы можете использовать для обеих этих задач. Всего за несколько строк awk
достигает того, что требует обширного кодирования на традиционном языке.
Эта мощь обеспечивается простой концепцией правил, содержащих шаблоны, которые выбирают текст для обработки и действия, определяющие обработку.
Linux Commands | ||
Files | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm · scp · gzip · chattr · cut · find · umask · wc | |
Processes | alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · yes · kill · sleep · sudo · su · time · groupadd · usermod · groups · lshw · shutdown · reboot · halt · poweroff · passwd · lscpu · crontab · date · bg · fg · pidof · nohup · pmap | |
Networking | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw · arping · firewalld |
RELATED: Best Linux Laptops for Developers and Enthusiasts