Przewodnik po średnio zaawansowanych skryptach awk

Ten artykuł omawia możliwości awk, które są łatwiejsze w użyciu teraz, gdy wiesz, jak ułożyć swoje polecenie w wykonywalny skrypt.

Operatory logiczne i warunkowe

Możesz użyć operatorów logicznych i (pisane &&) i lub (pisane ||), aby dodać specyficzność do twoich warunków.

Na przykład, aby wybrać i wydrukować tylko rekordy z ciągiem „fioletowy” w drugiej kolumnie i kwotą mniejszą niż pięć w trzeciej kolumnie:

$2 == "purple" && $3 < 5 {print $1}

Jeśli rekord ma „fioletowy” w kolumnie drugiej, ale wartość większą lub równą 5 w kolumnie trzeciej, to nie jest wybierany. Podobnie, jeśli rekord spełnia wymagania kolumny trzeciej, ale brakuje mu „fioletowego” w kolumnie drugiej, również nie jest wybierany.

Powiedzmy, że chcesz wybrać każdy rekord w pliku, w którym kwota jest większa lub równa 8 i wydrukować pasujący rekord z dwiema gwiazdkami (**). Chcesz również oznaczyć każdy rekord z wartością pomiędzy pięć (włącznie) a osiem tylko jedną gwiazdką (*). Jest kilka sposobów, aby to zrobić, a jednym z nich jest użycie polecenia next, aby poinstruować awk, że po wykonaniu akcji, powinien on zatrzymać skanowanie i przejść do następnego rekordu.

Tutaj przykład:

NR == 1 {
print $0;
next;
}
$3 >= 8 {
printf "%s\t%s\n", $0, "**";
next;
}
$3 >= 5 {
printf "%s\t%s\n", $0, "*";
next;
}
$3 < 5 {
print $0;
}

Komenda BEGIN

Komenda BEGIN pozwala drukować i ustawiać zmienne zanim awk rozpocznie skanowanie pliku tekstowego. Na przykład, możesz ustawić separatory pól wejściowych i wyjściowych wewnątrz skryptu awk, definiując je w instrukcji BEGIN. Ten przykład adaptuje prosty skrypt z poprzedniego artykułu dla pliku z polami ograniczonymi przecinkami zamiast białych znaków:

Komenda END

Komenda END, podobnie jak BEGIN, pozwala na wykonanie akcji w awk po zakończeniu skanowania przetwarzanego pliku tekstowego. Jeśli chcesz wydrukować łączne wyniki jakiejś wartości we wszystkich rekordach, możesz to zrobić dopiero po zakończeniu skanowania i przetworzeniu wszystkich rekordów.

Komendy BEGIN i END są uruchamiane tylko raz. Wszystkie reguły pomiędzy nimi są uruchamiane zero lub więcej razy na każdym rekordzie. Innymi słowy, większość skryptu awk jest pętlą, która jest wykonywana przy każdym nowym wierszu przetwarzanego pliku tekstowego, z wyjątkiem reguł BEGIN i END, które są uruchamiane przed i po pętli.

Oto przykład, który nie byłby możliwy bez polecenia END. Ten skrypt przyjmuje wartości z wyjścia uniksowego polecenia df i inkrementuje dwie zmienne niestandardowe (used i available) z każdym nowym rekordem.

$1 != "tempfs" {
used += $3;
available += $4;
}
END {
printf "%d GiB used\n%d GiB available\n", used/2^20, available/2^20;
}

Zapisz skrypt jako total.awk i wypróbuj go:

df -l | awk -f total.awk

Zmienne used i available działają jak zmienne w wielu innych językach programowania. Tworzysz je dowolnie i bez deklarowania ich typu, i dodajesz do nich wartości według własnego uznania. Na końcu pętli, skrypt dodaje rekordy w odpowiednich kolumnach razem i wypisuje sumy.

Matematyka

Jak zapewne możesz stwierdzić po wszystkich operatorach logicznych i zwykłych obliczeniach, awk radzi sobie z matematyką całkiem naturalnie. To prawdopodobnie czyni go bardzo użytecznym kalkulatorem dla twojego terminala. Zamiast zmagać się z zapamiętaniem dość niezwykłej składni bc, możesz po prostu użyć awk wraz z jego specjalną funkcją BEGIN, aby uniknąć wymogu argumentu pliku:

$ awk 'BEGIN { print 2*21 }'
42
$ awk 'BEGIN {print 8*log(4) }'
11.0904

Przyznać trzeba, że to wciąż dużo pisania dla prostej (i nie tak prostej) matematyki, ale nie potrzeba wiele wysiłku, aby napisać frontend, co jest ćwiczeniem do zbadania.

Ten artykuł został zaadaptowany z odcinka Hacker Public Radio, społecznościowego podcastu technologicznego.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *