Примеры использования Awk

Использование сокращений.

Конструкцию, используемую для вывода строк соответствующих заданной маске:
<span style="color: #461b7e;"> awk '{if ($0 ~ /pattern/) print $0}' </span>
можно сократить до
<span style="color: #461b7e;"> awk '/pattern/' </span>
Условие в awk может быть задано вне скобок, т.е. получаем:
<span style="color: #461b7e;"> awk '$0 ~ /pattern/ {print $0}' </span>
По умолчанию, действия производятся со всей строкой, $0 можно не указывать:
<span style="color: #461b7e;"> awk '/pattern/ {print}' </span>
print - является действием по умолчанию, его тоже можно не указывать.
<span style="color: #461b7e;"> awk '/pattern/' <span id="more-157"></span></span>
Для вывода значения первого столбца строки, в которой присутствует маска LEGO:
<span style="color: #461b7e;"> awk '/LEGO/ {print $1}' </span>
Для вывода значения первого столбца строки, во втором столбце которой присутствует маска LEGO:
<span style="color: #461b7e;"> awk '$2 ~ /LEGO/ {print $1}' </span>
Для замены слова LIGO на LEGO и вывода только измененных строк можно использовать:
<span style="color: #461b7e;"> awk '{if(sub(/LIGO/,"LEGO")){print}}' </span>
Но есть нужно выводить все строки (как sed 's/LIGO/LEGO/'), конструкцию можно упростить
(1 - true для всех строк):
<span style="color: #461b7e;"> awk '{sub(/LIGO/,"LEGO")}1' </span>
Вывести все строки, за исключением каждой шестой:
<span style="color: #461b7e;"> awk 'NR % 6' </span>
Вывести строки, начиная с 6 (как tail -n +6 или sed '1,5d'):
<span style="color: #461b7e;"> awk 'NR &gt; 5' </span>
Вывести строки, в которых значение второго столбца равно foo:
<span style="color: #461b7e;"> awk '$2 == "foo"' </span>
Вывести строки, в которых 6 и более столбцов:
<span style="color: #461b7e;"> awk 'NF &gt;= 6' </span>
Вывести строки, в которых есть слова foo и bar:
<span style="color: #461b7e;"> awk '/foo/ &amp;&amp; /bar/' </span>
Вывести строки, в которых есть слово foo, но нет bar:
<span style="color: #461b7e;"> awk '/foo/ &amp;&amp; !/bar/' </span>
Вывести строки, в которых есть слова foo или bar (как grep -e 'foo' -e 'bar'):
<span style="color: #461b7e;"> awk '/foo/ || /bar/' </span>
Вывести все непустые строки:
<span style="color: #461b7e;"> awk 'NF' </span>
Вывести все строки, удалив содержимое последнего столбца:
<span style="color: #461b7e;"> awk 'NF--' </span>
Вывести номера строк перед содержимым:
<span style="color: #461b7e;"> awk '$0 = NR" "$0' </span>
Заменим команды (пропускаем 1 строку, фильтруем строки с foo и заменяем foo на bar,
затем переводим в верхний регистр и выводим значение второго столбца)
<span style="color: #461b7e;"> cat test.txt | head -n +1 | grep foo | sed 's/foo/bar/' | tr '[a-z]' '[A-Z]' | cut -d ' ' -f 2 </span>
аналогичной конструкцией на awk:
<span style="color: #461b7e;"> cat test.txt | awk 'NR&gt;1 &amp;&amp; /foo/{sub(/foo/,"bar"); print toupper($2)}' </span>

Использование диапазонов.

Вывести группу строк, начиная со строки, в которой есть foo, и заканчивая
строкой, в которой есть bar:
<span style="color: #461b7e;"> awk '/foo/,/bar/' </span>
Исключив из вывода строки с вхождением заданных масок:
<span style="color: #461b7e;"> awk '/foo/,/bar/{if (!/foo/ &amp;&amp; !/bar/)print}' </span>
Более оптимальный вариант:
<span style="color: #461b7e;"> awk '/bar/{p=0};p;/foo/{p=1}' </span>
Исключить только строку с завершающим вхождением (bar)
<span style="color: #461b7e;"> awk '/bar/{p=0} /foo/{p=1} p' </span>
Исключить только строку с начальным вхождением (foo)
<span style="color: #461b7e;"> awk 'p; /bar/{p=0} /foo/{p=1}' </span>

Разбиение файла по шаблонам.

Имеется файл (file), в котором группы строк разделены шаблонами FOO1,FOO2 и т.д.
Необходимо записать данные, находящиеся между метками FOO в разные файлы,
соответствующие указанным в FOO номерам.
<span style="color: #461b7e;"> awk -v n=1 '/^FOO[0-9]*/{close("out"n);n++;next} {print &gt; "out"n}' file </span>
В GNU Awk можно сделать так:
<span style="color: #461b7e;"> LC_ALL=C gawk -v RS='FOO[0-9]*\n' -v ORS= '{print &gt; "out"NR}' file </span>

Парсинг CSV.

По умолчанию в качестве разделителя используются пробел и табуляция.
Чтобы определить иной разделитель, например запятую, нужно использовать FS=',' или опцию "-F".
В качестве параметра может быть задано регулярное выражение, например, FS='^ *| *, *| *$'
Но для разбора CSV это не подойдет, так как пробелы могут присутствовать и внутри трок,
поэтому проще вырезать лидирующие пробелы перед и после запятой:

<span style="color: #461b7e;"> FS=',' for(i=1;i&lt;=NF;i++){ gsub(/^ *| *$/,"",$i); print "Field " i " is " $i; } </span>
Если в CSV данные помещены в кавычки, например "field1","field2", то подойдет такой скрипт:

<span style="color: #461b7e;"> FS=',' for(i=1;i&lt;=NF;i++){ gsub(/^ *"|" *$/,"",$i); print "Field " i " is " $i; } </span>
Но скрипт придется усовершенствовать для разбора полей вида:

field1, "field2,with,commas"  ,  field3  ,  "field4,foo"

<span style="color: #461b7e;"> $0=$0","; while($0) { match($0,/[^,]*,| *"[^"]*" *,/); sf=f=substr($0,RSTART,RLENGTH); gsub(/^ *"?|"? *,$/,"",f); print "Field " ++c " is " f; sub(sf,""); } </span>

Проверка IPv4 адреса.

<span style="color: #461b7e;"> awk -F '[.]' 'function ok(n) { return (n ~ /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/) } {exit (ok($1) &amp;&amp; ok($2) &amp;&amp; ok($3) &amp;&amp; ok($4))}' </span>

Сравнение двух файлов.

Вывод всех дублирующихся строк из двух неотсортированных файлах file1 и file2:
<span style="color: #461b7e;"> awk '!($0 in a) {c++;a[$0]} END {exit(c==NR/2?0:1)}' file1 file2 </span>

Вывод только выделенных блоков текста.

Например, чтобы показать из файла с текстом только текст, отмеченный как =текст=
можно использовать:
<span style="color: #461b7e;"> awk -v RS='=' '!(NR%2)' </span>
с форматированием переносов строк:
<span style="color: #461b7e;"> awk -v RS='=' '!(NR%2){gsub(/\n/," ");print}'</span>