Инструменты пользователя

Инструменты сайта


awk

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
awk [2015/10/10 05:48]
sander
awk [2015/11/12 09:00] (текущий)
sander [Массивы]
Строка 1: Строка 1:
 +====== AWK ======
 +
 +Программа awk автоматически делит каждую прочитанную строку на поля - строки символов разделенные знаками табуляции. Этим полям она присваивает имена $1, $2, $3 и т.д., $NF переменная содержащая количество полей в строке.\\
 +<​code>​
 +Пр. who | awk '​{print $1,​$4}'​
 +Пр. df -h | grep /dev/ | awk '​{print $1,​$5}'​
 +</​code>​
 +Параметр -F позволяет задать разделитель.\\
 +<​code>​
 +Пр. tail -n4 /etc/passwd | awk -F: '​{print $1}'
 +</​code>​
 +Переменная NR хранит номер текущей строки.\\
 +<​code>​
 +Пр. tail -n4 /etc/passwd | awk -F: '​{print NR, $1}'
 +Пр. cat /etc/passwd | awk -F: '​{print NR, "​User:",​$1,",​shel:",​$7}'​
 +</​code>​
 +
 +Поле $0 представляет всю входную строку целиком.\\
 +
 +В операторе print значения разделяемые запятыми печатаются через разделитель выходных полей, по умолчанию это пробел.\\
 +\\
 +<​code>​
 +Проверим есть ли пользователь с именем root.
 +Пр. awk -F: '​$1=="​root"'​ /etc/passwd
 +Проверим есть ли пользователи без пароля.
 +Пр. awk -F: '​$2==""'​ /etc/passwd
 +аналогично можно использовать:​
 +awk -F: '$2 ~ /^$/' /etc/passwd Второе поле совпадает с пустой строкой,​ ~ указывает на использование регулярного выражения,​ которое заключено между символами косой черты.
 +awk -F: '$2 !~ /./' /etc/passwd Второе поле не соответствует никакому символу.
 +awk -F: '​length($2)==0'​ /etc/passwd Длина второго поля равна 0. length встроенная функция awk, считающая длину строки.
 +
 +
 +awk 'NF % 2 != 0' /etc/passwd Печатать,​ если число полей четно.
 +awk 'NF % 2 == 0' /etc/passwd Печатать,​ если число полей не четно.
 +</​code>​
 +
 +Пр. вывести диск, если его заполненность больше 70%\\
 +<​code>​
 +df | awk '​($3*100/​$2) > 70 {print $1}'
 +</​code>​
 +Функция substr(s,​m,​n) возвращает строку s, начиная с позиции m, длиной n символов.\\
 +<​code>​
 +Пр. date | awk '​{print substr($4,​1,​5)}'​
 +12:07
 +</​code>​
 +===== Шаблоны BEGIN и END. =====
 +
 +BEGIN позволяет выполнять действия до того как будет прочитана первая строка ввода (инициализация переменных,​ вывод заголовков)\\
 +END определяет действия после того как будет прочитана последняя строка (напечатает число выходных строк)\\
 +
 +===== Арифметические выражения awk. =====
 +<​code>​
 +Пр. {s=s+$1}
 +Пр. awk '{s = s+ substr($8,​6,​9)} END {print s, s/NR}' ping.log
 +Пр. df | awk '{s = $4*100/​$2} ​ {print "На диске:",​ $1,"​свободного места:",​ substr(s,​1,​2) "​%"​}'​ | grep /sd
 +</​code>​
 +
 +===== Встроенные переменные awk. =====
 +
 +| FILENAME | имя текущего входного файла| ​
 +| FS | разделитель полей, пробел или табуляция по умолчанию| ​
 +| NF | количество полей во входной записи| ​
 +| NR | номер выводимой записи| ​
 +| OFMT | формат вывода для чисел| ​
 +| OSF | разделитель полей входных строк| ​
 +| OSR | разделитель выходных строк| ​
 +| RS | разделитель входных записей| ​
 +
 +===== Операторы awk =====
 +<​code>​
 += += -= *= /= %= присваиваие
 +|| логическое или: expr1 || expr2 истино,​ если истинен любой из операндов
 +&& логическое и: expr1 && expr2 истино,​ если истины оба операнда
 +Пр. awk '​NR==13 || NR==12'​ /etc/passwd
 +Пр. awk '​NR==13 && NR==13'​ /etc/passwd
 +! инвертирование результата выражения
 +> >= < <= == != ~ !~ операторы сравнения;​ ~ - совпадение,​ !~ - не совпадение
 ++ - плюс и минус
 +* / % умножение,​ деление,​ вычитание остатка
 +++ -- инкремент и декремент
 +</​code>​
 +
 +===== Операторы управления. =====
 +
 +<​code>​
 +if (условие)
 + оператор1
 +else
 + оператор2
 +</​code>​
 +<​code>​
 +for (выражение1;​ условие;​ выражение2)
 + оператор
 +</​code>​
 +<​code>​
 +Пр. for (i = 2; i <= NF; i++)
 +</​code>​
 +<​code>​
 +выражение1
 + while (условие) {
 + оператор
 + выражение2
 + }
 +
 +
 +</​code>​
 +
 +===== Массивы =====
 +
 +
 +Пр. печатает файл /etc/passwd в обратном порядке.\\
 +<code bash>
 +awk ' {line[NR] = $0}
 +END {for (i = 1 ; i!=NR ; i++) print line[i]} ' /etc/passwd
 +
 +awk '​{line[NR]=$0} {i=NR} END {while (i!=0) {print line[i] i--}}' /etc/passwd
 +</​code>​
 +Массивы не требуют объявления;​ размер массива ограничен объемом оперативной памяти.\\
 +\\
 +===== Встроенные функции в awk. =====
 +
 +<​code>​
 +cos(expr) косинус expr
 +exp(expr) экспоненциальная функция
 +getline() вывод очередной строки,​ возвращает 0, если достигнут конец файла, иначе 1
 +index(s1,​s2) положение строки s2 в строке s1, возвращает 0, если подстрока не найдена
 +int(expr) целая часть expr, дробная часть отбрасывается
 +Пр. df | awk ' {if (index($1,"/​dev/​s"​)==1) print $1,​int($4*100/​$2)}'​
 +length(s) длина строки s
 +log(expr) натуральный логорифм expr
 +sin(expr) синус expr
 +split(s,​a,​c) разбиение строки s на элементы a[1]...a[n] по символу c, возвращает n
 +sprintf(frm,​...) формотировать согласно спецификации frm
 +substr(s,​n,​m) подстрока строки s длиной n, начиная с позиции m.
 +</​code>​
 +
 +===== Ассоциаивные масивы =====
 +
 +При обработке данных возникает необходимость хранения набора пар имя-значение
 +sum \\
 +| usie | 100| 
 +| John | 200| 
 +| Mary | 300| 
 +| Mary | 400| 
 +| John | 500| 
 +| Susie | 600| 
 +| Mary | 700| 
 +\\
 +<​code>​
 +awk '​{sum[$1]+=$2} END {for (name in sum) print name,​sum[name]}'​ sum 
 +
 +Mary 1400
 +John 700
 +usie 100
 +Susie 600
 +</​code>​
 +===== Переменные в awk =====
 +<​code>​
 +#!/bin/bash
 +
 +log="/​var/​log/​fail2ban.log"​
 +day=$(date +%Y-%m-%d)
 +
 +awk -v d=$day '{if ($1==d && $7=="​Ban"​) ip[$8]+=1} END {for (i in ip) print  ip[i], i}' $log | sort -r
 +#или
 +awk  '{if ($1==d && $7=="​Ban"​) ip[$8]+=1} END {for (i in ip) print  ip[i], i}' d=$day $log | sort -r
 +</​code>​
 +
 +===== Полезности =====
 +
 +Ищем первых 5 пользователей по потреблению памяти в %\\
 +<​code>​
 +ps aux | awk '​{mem[$1]+=$4} END {for (user in mem) print user,​mem[user] }' | sort -rdk2 | head -n5
 +</​code>​
 +Выводим диски на которых использовано более 60% памяти\\
 +<​code>​
 +df  | awk '​{use=($3*100/​$2)}{if(use>​6&&​$1~/​\/​dev*/​)print$1,​int(use)"​%"​}'​
 +</​code>​
 +Вывести все значимые строки конфига(исключаем комментарии и пустые строки)\\
 +<​code>​
 +awk '{if ($0!~/^$/ && $0!~/^#/) print $0}' /​etc/​adduser.conf ​
 +</​code>​
 +Топ заблокированных ip в fail2ban
 +<​code>​
 +awk '​{if($7=="​Ban"​)ip[$8]+=1 } END  {for (i in ip) print ip[i],​i}'​ /​var/​log/​fail2ban.log | sort -r
 +</​code>​
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
  
awk.txt · Последние изменения: 2015/11/12 09:00 — sander