Примеры использования Awk
Использование сокращений.
Конструкцию, используемую для вывода строк соответствующих заданной маске: awk '{if ($0 ~ /pattern/) print $0}' можно сократить до awk '/pattern/' Условие в awk может быть задано вне скобок, т.е. получаем: awk '$0 ~ /pattern/ {print $0}' По умолчанию, действия производятся со всей строкой, $0 можно не указывать: awk '/pattern/ {print}' print - является действием по умолчанию, его тоже можно не указывать. awk '/pattern/' Для вывода значения первого столбца строки, в которой присутствует маска LEGO: awk '/LEGO/ {print $1}' Для вывода значения первого столбца строки, во втором столбце которой присутствует маска LEGO: awk '$2 ~ /LEGO/ {print $1}' Для замены слова LIGO на LEGO и вывода только измененных строк можно использовать: awk '{if(sub(/LIGO/,"LEGO")){print}}' Но есть нужно выводить все строки (как sed 's/LIGO/LEGO/'), конструкцию можно упростить (1 - true для всех строк): awk '{sub(/LIGO/,"LEGO")}1' Вывести все строки, за исключением каждой шестой: awk 'NR % 6' Вывести строки, начиная с 6 (как tail -n +6 или sed '1,5d'): awk 'NR > 5' Вывести строки, в которых значение второго столбца равно foo: awk '$2 == "foo"' Вывести строки, в которых 6 и более столбцов: awk 'NF >= 6' Вывести строки, в которых есть слова foo и bar: awk '/foo/ && /bar/' Вывести строки, в которых есть слово foo, но нет bar: awk '/foo/ && !/bar/' Вывести строки, в которых есть слова foo или bar (как grep -e 'foo' -e 'bar'): awk '/foo/ || /bar/' Вывести все непустые строки: awk 'NF' Вывести все строки, удалив содержимое последнего столбца: awk 'NF--' Вывести номера строк перед содержимым: awk '$0 = NR" "$0' Заменим команды (пропускаем 1 строку, фильтруем строки с foo и заменяем foo на bar, затем переводим в верхний регистр и выводим значение второго столбца) cat test.txt | head -n +1 | grep foo | sed 's/foo/bar/' | tr '[a-z]' '[A-Z]' | cut -d ' ' -f 2 аналогичной конструкцией на awk: cat test.txt | awk 'NR>1 && /foo/{sub(/foo/,"bar"); print toupper($2)}' Использование диапазонов. Вывести группу строк, начиная со строки, в которой есть foo, и заканчивая строкой, в которой есть bar: awk '/foo/,/bar/' Исключив из вывода строки с вхождением заданных масок: awk '/foo/,/bar/{if (!/foo/ && !/bar/)print}' Более оптимальный вариант: awk '/bar/{p=0};p;/foo/{p=1}' Исключить только строку с завершающим вхождением (bar) awk '/bar/{p=0} /foo/{p=1} p' Исключить только строку с начальным вхождением (foo) awk 'p; /bar/{p=0} /foo/{p=1}' Разбиение файла по шаблонам. Имеется файл (file), в котором группы строк разделены шаблонами FOO1,FOO2 и т.д. Необходимо записать данные, находящиеся между метками FOO в разные файлы, соответствующие указанным в FOO номерам. awk -v n=1 '/^FOO[0-9]*/{close("out"n);n++;next} {print > "out"n}' file В GNU Awk можно сделать так: LC_ALL=C gawk -v RS='FOO[0-9]*\n' -v ORS= '{print > "out"NR}' file Парсинг CSV. По умолчанию в качестве разделителя используются пробел и табуляция. Чтобы определить иной разделитель, например запятую, нужно использовать FS=',' или опцию "-F". В качестве параметра может быть задано регулярное выражение, например, FS='^ *| *, *| *$' Но для разбора CSV это не подойдет, так как пробелы могут присутствовать и внутри трок, поэтому проще вырезать лидирующие пробелы перед и после запятой: FS=',' for(i=1;i<=NF;i++){ gsub(/^ *| *$/,"",$i); print "Field " i " is " $i; } Если в CSV данные помещены в кавычки, например "field1","field2", то подойдет такой скрипт: FS=',' for(i=1;i<=NF;i++){ gsub(/^ *"|" *$/,"",$i); print "Field " i " is " $i; } Но скрипт придется усовершенствовать для разбора полей вида: field1, "field2,with,commas" , field3 , "field4,foo" $0=$0","; while($0) { match($0,/[^,]*,| *"[^"]*" *,/); sf=f=substr($0,RSTART,RLENGTH); gsub(/^ *"?|"? *,$/,"",f); print "Field " ++c " is " f; sub(sf,""); } Проверка IPv4 адреса. awk -F '[.]' 'function ok(n) { return (n ~ /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/) } {exit (ok($1) && ok($2) && ok($3) && ok($4))}' Сравнение двух файлов. Вывод всех дублирующихся строк из двух неотсортированных файлах file1 и file2: awk '!($0 in a) {c++;a[$0]} END {exit(c==NR/2?0:1)}' file1 file2 Вывод только выделенных блоков текста. Например, чтобы показать из файла с текстом только текст, отмеченный как =текст= можно использовать: awk -v RS='=' '!(NR%2)' с форматированием переносов строк: awk -v RS='=' '!(NR%2){gsub(/\n/," ");print}'