Главная

Saturday, 24 October 2020

Потоковый редактор awk #2.

Всем привет.

В отличии от sed потоковый редактор awk - это еще и язык программирования, в котором есть переменные, управляющие конструкции, циклы и т.п. По этой причине awk - более мощный редактор, но менее быстрый.

# Ключевые слова awk:

* BEGIN

* break

* close

* continue

* END

* exit

* exp

* FILENAME

* for * FS

* getline

* if

* in

* index

* int

* length

* log

* next * NF

* NR

* number

* OFMT

* OFS

* ORS

* print

* printf

* RS * split

* sprintf

* sqrt

* string

* substr

* while


# Арифметические операции awk:

=    ++   --

+    -    *    /

+=   -=   *=   /=

%    %=


# Операции сравнения:

=   !=   <   >   <=   >=


# Логические операции:

&&   ||   !


# Операции сопоставления:

~   !~


# Специальные переменные

$0  - текущая входная запись

$1, $2 ... - поле в текущей записи

NF  - общее число полей

NR  - номер текущей записи

RS  - текущий разделитель записей

FS  - текущий разделитель полей

OFS - выходной разделитель полей

ORS - выходной разделитель записей

FILENAME - имя обрабатываемого файла


# Функции:

# экспонента

exp(число)

# округление

int(число)

# логарифм

log(число)

# корень

sqrt(число)

# получить новую строку

getline

# найти индекс строки (первый = 0)

index(строка, поисковая строка)

# длина записи

length

# длина выражения

length(выражение)

# разделить через сепаратор

split(выражение, массив, сепаратор)

# разделить через FS

split(выражение, массив)

# форматировать

sprintf(формат, выражение1, выражение2 ...)

# вырезать подстроку

substr(выражение, pos)

# вырезать отрезок строки

substr(выражение, pos, length)


# Пример простой программы на awk - эмуляция grep:

$ awk '/xxx/ { print }' file


# Чтобы посчитать число строк в файле, можно написать так:

awk 'BEGIN {x=0} {x++} END {print x}' file


При этом, переменные можно задавать снаружи awk:

awk '{x++} END {print x}' x=1 file


# awk может принимать параметры:

#!/usr/bin/awk -f

BEGIN {

    for (i = 1; i < ARGC; i++) {

        if (ARGV[i] ~ /^[A-Za-z]+$/ || ARGV[i] == "-")

            print ARGV[i]

        else if (ARGV[i] ~ /^[0-9]+$/)

            continue

        else

            break

    }

}


# И использовать циклы for, while:

# распечатать все поля по строкам

{ i = 1

  while (i <= NF) {

    print $i

    ++i

  }

}


awk умеет перенапралять результаты в файл или в пайп, причем уже после завершения своей работы:

#!/usr/bin/awk -f

{

  if ($1 ~ "^str") print $1 | "sort"

}


Перед блоками внутри кода awk можно задавать условия отбора (как в sed):

/Moscow/ { ... }

$1 == $3 && $2 < 5 { ... }

$4 ~ /^(Asia|Africa)$/ { ... }

/from/, /to/ { ... }

NR==1, NR==5 { ... }


Такие выражения можно использовать для поиска максимума, к примеру:

maxval < $1 {

  maxval = $1

  maxitem = $2

}

END {

  print maxitem, maxvalue

}


awk поддерживает массивы - и они могут быть ассоциативными:

{ use [$1" "$2] = $3 }

END {

  for (np in use)

    print np "t" use[np] | "sort +0 +2nr"

}


awk позволяет пользоваться функциями:

#!/usr/bin/awk -f

function x(s) {

   print substr(s,0,1)

}

{ x($0) }


Поскольку awk очень похож на обычный язык программирования, выучить и применять awk

проще, чем sed. Чего и всем советую: прежде чем решать какую-то мелкую текущую задачу

на php, perl, python и т.п - попробуйте bash и awk - скорее всего всё получится.


awk - суммирование столбца, например так:

awk 'BEGIN {FS = "|"} {sum+=$1} END {print sum}' filename.txt 

или так:

awk 'BEGIN {FS = "|"} ; $1 ~ /^smith$/ {sum+=$3} END {print sum}'

или даже так:

awk '{a[$1] += $3} END {for (i in a) print i, a[i]}' filename.txt 


Успехов.

No comments:

Post a Comment

А что вы думаете по этому поводу?