- AWK: Примеры программ
- Способы запуска awk-программ
- Фильтрация строк с помощью awk
- Отбор строк, соответствующих регулярному выражению
- Отбор строк, НЕ соответствующих регулярному выражению
- Отбор строк из заданного диапазона
- Комбинирование условий фильтрации
- Отбор строк по условиям относительно отдельных слов
- Работа со строками в awk
- Форматированный вывод
- Функции преобразования
- Условные конструкции
- Переменные
- Циклы
- Нестандартный разделитель слов
- Комбинирование фильтров и команд печати
- Команда awk в Linux
- Возможности команды awk
- Синтаксис
- Использование команды awk в Linux
- Вывод содержимого файла
- Счётчик номеров строк
- Вывод определённых столбцов
- Вывод определённых строк
- Вывод строк с определённым шаблоном
- Использование регулярных выражений
- Использование операторов сравнения
- Заключение
AWK: Примеры программ
Утилита awk является примером классического приложения Linux для обработки текста. Она весьма универсальна и эффективна, хоть и не предоставляет полноценный язык программирования. Однако будьте уверены, что ее возможностей вполне хватит для решения многих задач автоматизированной обработки текста (особенно при комбинировании с другими консольными утилитами).
Способы запуска awk-программ
Если awk -программа достаточно простая и короткая, то ее код можно набрать прямо в консоли:
В качестве входных данных для awk можно использовать не только текстовые файлы, но и вывод в стандартный поток других приложений:
В случае, когда код awk -программы достаточно объемный или должен быть сохранен для повторного использования, его можно вызывать из файла с ключом -f :
Для проведения экспериментов используем файл test.cpp , на котором будем проверять результаты работы awk — программ:
#include #include #include void test1(); int test2(); // Комментарий в стиле С для функции main() int main( int argc, char** argv ) < std::cout return 0; > // Комментарий в стиле С для функции test1() void test1() < std::cout // Комментарий в стиле С для функции test2() int test2()
Фильтрация строк с помощью awk
В первую очередь awk позволяет отбирать строки из текста на основе регулярных выражений и некоторых числовых условий.
Отбор строк, соответствующих регулярному выражению
Например, чтобы получить все строки файла test.cpp , содержащие директиву препроцессора #include , воспользуемся следующей командой:
Регулярное выражение записывается между двумя символами / . В результате получим:
Отбор строк, НЕ соответствующих регулярному выражению
Чтобы оставить все строки, которые не соответствуют регулярному выражению, воспользуйтесь командой из предыдущего подраздела и поставьте в начало awk -кода восклицательный знак. Например, так мы исключим все закомментированные строки:
#include #include #include void test1(); int test2(); int main( int argc, char** argv ) < std::cout return 0; > void test1() < std::cout int test2()
Отбор строк из заданного диапазона
Определить диапазон строк для вывода на экран можно с помощью двух регулярных выражений, записанных через запятую. В качестве примера найдем определение всех функций, возвращающих int :
int main( int argc, char** argv ) < std::cout return 0; > int test2()
Комбинирование условий фильтрации
Для проверки строк сразу по нескольким условиям используйте операторы && (И) и || (ИЛИ) .
Следующая команда выводит все комментарии, которые не содержат main :
// Комментарий в стиле С для функции test1() // Комментарий в стиле С для функции test2()
Ранее мы искали диапазон строк по двум регулярным выражениям, но если номера строк, которые нужно вывести, известные заранее, то все упрощается:
NR - переменная awk , которая определяет номер строки. Таким образом, представленный код выводит 5-ую и 6-ую строки:
Отбор строк по условиям относительно отдельных слов
Awk может фильтровать текст не только по строкам, но и по отдельным словам. На i -ое слово в строке можно сослаться с помощью $i . Нумерация начинается с единицы, а $0 определяет содержимое всей строки. Количество слов в строке определяется с помощью переменной NF , поэтому $NF указывает на последнее слово. Например, найдем строки, первым словом которых является int или void :
awk '$1 == "int" || $1 == "void"' test.cpp
Соответствующий вывод на консоль:
void test1(); int test2(); int main( int argc, char** argv ) < void test1() < int test2()
Однако проще использовать проверку по регулярному выражению для слова. Для этого в awk предусмотрен специальный оператор ~ , который нужно поставить между переменной, указывающей на слово, и регулярным выражением. В качестве примера перепишем предыдущую команду в более компактном виде:
Отбор строк на основе числовых характеристик
В awk доступны арифметические операторы языка C, что открывает свободу действий. Пример ниже выводит все четные строки ( NR - номер строки):
#include int test2(); // Комментарий в стиле С для функции main() std::cout return 0; void test1() < >// Комментарий в стиле С для функции test2() std::cout
Следующая awk -программа выводит все строки, у которых длина 1-ого слова равна трем:
int test2(); int main( int argc, char** argv ) < int test2()
Далее приводится код для вывода строк, состоящих из двух слов ( NF - количество слов в строке):
#include #include #include void test1(); int test2(); return 0;
Работа со строками в awk
Как вы могли убедиться, awk обладает неплохим набором функций для фильтрации строк текста. Однако для этих строк еще можно выполнять различные преобразования. Команды для работы со строками должны быть обернуты в фигурные скобки < … >. Код в скобках последовательно вызывается для каждой строки обрабатываемого текста.
Форматированный вывод
В awk имеется прямой аналог функции printf() языка C . В качестве примера выведем в начале каждой строки ее номер:
1 #include 2 #include 3 #include 4 5 void test1(); 6 int test2(); 7 8 // Комментарий в стиле С для функции main() 9 int main( int argc, char** argv ) < 10 std::cout 15 16 return 0; 17 > 18 19 // Комментарий в стиле С для функции test1() 20 void test1() < 21 std::cout 23 24 // Комментарий в стиле С для функции test2() 25 int test2()
Функции преобразования
Кроме printf() есть в awk и другие функции. Например, print() и toupper() :
#INCLUDE #INCLUDE #INCLUDE VOID TEST1(); INT TEST2(); // КОММЕНТАРИЙ В СТИЛЕ С ДЛЯ ФУНКЦИИ MAIN() INT MAIN( INT ARGC, CHAR** ARGV ) < STD::COUT RETURN 0; > // КОММЕНТАРИЙ В СТИЛЕ С ДЛЯ ФУНКЦИИ TEST1() VOID TEST1() < STD::COUT // КОММЕНТАРИЙ В СТИЛЕ С ДЛЯ ФУНКЦИИ TEST2() INT TEST2()
Условные конструкции
В awk -программах доступны операторы if-else . Например, следующий код выводит без изменения строки, у которых на 1-ой позиции стоит int , а на последней - < , иначе на консоль отправляется --- :
Выполнение кода приводит к выводу следующего:
--- --- --- --- --- --- --- --- int main( int argc, char** argv ) < --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- int test2() < --- ---
Переменные
Доступны в awk -программах и переменные, которые не требуется предварительно объявлять. Следующий код для подсчета количества строк и слов в тексте поместим в файл stat.awk :
Тогда его вызов осуществляется следующим образом:
line count: 27, word count: 88
Фильтр END указывает, что код в скобках после него должен выполняться только после прохода всех строк. Доступен в awk и фильтр BEGIN , поэтому в более общем случае программа принимает вид:
Обратите внимание, что посчитать строки и слова в тексте намного проще с помощью wc :
Циклы
В awk -программах вам также доступны циклы for и while в стиле C . Для примера выведем все строки в обратном порядке. Создадим файл reverse.awk следующего содержимого:
< for( i = NF; i >0; --i ) printf "%s ", $i; printf "\n" >
Вызовем программу следующий образом:
В результате слова в каждой строке будут выведены в обратном порядке:
#include #include #include test1(); void test2(); int main() функции для С стиле в Комментарий // < ) argv char** argc, int main( int std::endl; 0; return > test1() функции для С стиле в Комментарий // < test1() void std::endl; test2() функции для С стиле в Комментарий //
Нестандартный разделитель слов
По умолчанию awk в качестве разделителя слов использует пробельные символы, однако такое поведение можно изменить. Для этого воспользуйтесь ключом -F , после которого укажите строку, определяющую разделитель. Например, следующая программа выводит название группы и ее пользователей (если в группе есть пользователи) из файла /etc/group , применяя в качестве разделителя символ двоеточия:
Комбинирование фильтров и команд печати
Все рассмотренные ранее фильтры можно использовать совместно с командами обработки строк. Достаточно записать ограничения перед фигурными скобками. Ниже представлен пример для вывода первых 9 строк вывода команды ps , содержащей информацию о пользователе, идентификаторе процесса и имени команды:
USER PID COMMAND root 1 /sbin/init root 2 [kthreadd] root 3 [ksoftirqd/0] root 5 [kworker/0:0H] root 7 [rcu_preempt] root 8 [rcu_sched] root 9 [rcu_bh] root 10 [migration/0]
Команда awk в Linux
В Linux команда awk используется в командной строке для обработки текста. Она позволяет выполнять действия над строками в соответствии с заданным шаблоном.
Скриптовый язык awk не требует компиляции и позволяет пользователю использовать переменные, числовые функции, строковые функции и логические операторы при написании крошечных, но очень эффективных программ.
Возможности команды awk
Утилита способна выполнять следующие операции:
- сканирование файла построчно;
- разбиение каждую строку ввода на поля;
- сравнивание строки/поля ввода с образцом;
- действия над совпавшими строками;
- преобразование файлов данных;
- создание форматированных отчетов;
- форматирование строк вывода;
- арифметические и строковые операции;
- условные операторы и циклы.
Синтаксис
Использование команды awk в Linux
Для ознакомления с использованием утилиты создаём простой текстовый файл:
oleg@mobile:~/Directory:$ touch example1.txt oleg@mobile:~/Directory:$
Наполняем созданный файл текстом и смотрим полученный результат:
oleg@mobile:~/Directory:$ cat example.txt fristName lastName age city ID Ivan Ivanov 28 Toronto 400 Peter Petrov 43 Berlin 600 Sidor Sidorov 52 Sofia N/A Paul Pavlov 33 London 300 Carl Carlson 30 Rome N/A oleg@mobile:~/Directory:$
В созданном файле 5 столбцов: fristName , lastName , age , city , ID .
Вывод содержимого файла
Чтобы вывода всего содержимого файла, внутри фигурных скобок следует указать действие print $0 :
oleg@mobile:~/Directory:$ awk '' example.txt fristName lastName age city ID Ivan Ivanov 28 Toronto 400 Peter Petrov 43 Berlin 600 Sidor Sidorov 52 Sofia N/A Paul Pavlov 33 London 300 Carl Carlson 30 Rome N/A oleg@mobile:~/Directory:$
Счётчик номеров строк
Для того чтобы каждая строка имела счетчик номеров строк, следует использовать встроенную переменную NR :
oleg@mobile:~/Directory:$ awk '' example.txt 1 fristName lastName age city ID 2 3 Ivan Ivanov 28 Toronto 400 4 Peter Petrov 43 Berlin 600 5 Sidor Sidorov 52 Sofia N/A 6 Paul Pavlov 33 London 300 7 Carl Carlson 30 Rome N/A oleg@mobile:~/Directory:$
Вывод определённых столбцов
При использовании команды awk можно указать в выводе лишь определённые столбцы. Для примера выводим первый столбец:
oleg@mobile:~/Directory:$ awk '' example.txt fristName Ivan Peter Sidor Paul Carl oleg@mobile:~/Directory:$
Для вывода второго столбца используется, естественно, $2 :
oleg@mobile:~/Directory:$ awk '' example.txt lastName Ivanov Petrov Sidorov Pavlov Carlson oleg@mobile:~/Directory:$
Для вывода более одного столбца, например, первого, второго и четвертого выполняется следующее:
oleg@mobile:~/Directory:$ awk '' example.txt fristName lastName city Ivan Ivanov Toronto Peter Petrov Berlin Sidor Sidorov Sofia Paul Pavlov London Carl Carlson Rome oleg@mobile:~/Directory:$
Для вывода последнего столбца можно использовать $NF , представляющее последнее поле в записи:
oleg@mobile:~/Directory:$ awk '' example.txt ID 400 600 N/A 300 N/A oleg@mobile:~/Directory:$
Вывод определённых строк
Можно выводить и определённые строки, например, из выбранного столбца. Для примера выводим первую строку первого столбца:
oleg@mobile:~/Directory:$ awk '' example.txt ID 400 600 N/A 300 N/A oleg@mobile:~/Directory:$
Разберём выполненную команду. awk '' example.txt вывела первый столбец. Затем выходные данные этой команды были переданы с помощью символа вертикальной черты | в команду head , где её аргумент -1 выбрал первую строку столбца.
Следовательно, при желании вывести две строки, например первую и вторую необходимо выполнить следующее:
oleg@mobile:~/Directory:$ awk '' example.txt | head -2 fristName oleg@mobile:~/Directory:$
Обратите внимание на то, что вторая строка пробельная.
Вывод строк с определённым шаблоном
oleg@mobile:~/Directory:$ awk '/^P/' example.txt Peter Petrov 43 Berlin 600 Paul Pavlov 33 London 300 oleg@mobile:~/Directory:$
Команды выбрала в нашем файле, две строки, начинающиеся с буквы P , а символом стрелки вверх ^ было указано начало строки.
Можно также вывести строки, заканчивающиеся определённым шаблоном:
oleg@mobile:~/Directory:$ awk '/0$/' example.txt Ivan Ivanov 28 Toronto 400 Peter Petrov 43 Berlin 600 Paul Pavlov 33 London 300 oleg@mobile:~/Directory:$
Эту команду также можно изменить следующим образом:
oleg@mobile:~/Directory:$ awk '! /0$/' example.txt fristName lastName age city ID Sidor Sidorov 52 Sofia N/A Carl Carlson 30 Rome N/A oleg@mobile:~/Directory:$
Теперь были выведены строки не заканчивающиеся на 0 , так как символ ! используется как NOT.
Использование регулярных выражений
Для вывода слов, содержащих определённые буквы, соответствующие указанному шаблону, используется слеш / . Например, для вывода слов, содержащих Pa , выполняется следующее:
oleg@mobile:~/Directory:$ awk ' /Pa/' examle.txt Paul Pavlov 33 London 300 oleg@mobile:~/Directory:$
В выводе мы получили все строки, содержащие Pa .
Использование операторов сравнения
Для получения, например, всей информации о сотрудниках моложе 35 лет оператор сравнения используются следующим образом:
oleg@mobile:~/Directory:$ awk ' /Pa/' examle.txt Paul Pavlov 33 London 300 oleg@mobile:~/Directory:$
Команда показала в выводе всех сотрудников моложе 35 лет.
Заключение
Здесь были изложены лишь основы работы в Linux с командой awk . Теперь зная их вы сможете углублять свои навыки работы с этой очень мощной утилитой.