POCZĄTEK i KONIEC za pomocą polecenia awk

13

Zgodnie z instrukcją awk BEGIN i END nie są używane do dopasowania danych wejściowych, ale raczej do dostarczania informacji o uruchamianiu i czyszczeniu do skryptu awk. Oto podany przykład:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Najpierw wypisuje ciąg do wyjścia. Następnie sprawdza dane wejściowe pod kątem dopasowania wzorca, gdzie dane wejściowe zaczynają się od a lub x, po którym następuje jeden lub wiele znaków, po których następuje .conf. Dla dowolnych dopasowań drukowana jest 9. kolumna.

Czy to oznacza, że ​​awk może używać tylko jednej funkcji drukowania, która zawiera BEGIN lub END? Jeśli nie, to dlaczego nie możemy po prostu użyć funkcji drukowania na początku bez słowa kluczowego BEGIN? Wygląda na to, że BEGIN jest zbędny.

JohnMerlino
źródło
Wystarczy uruchomić polecenie bez BEGIN, by odpowiedzieć na twoje pytanie, pokazując, że nie jest to zbyteczne i że uzyskasz inny wynik.
msb

Odpowiedzi:

11

To BEGINnie jest zbyteczne. Jeśli użytkownik nie określi BEGINwówczas printbyłyby wykonywane dla każdej linii wejścia.

Cytowanie z instrukcji :

BEGINReguła jest wykonywana tylko raz, przed pierwszym rekordem wejście. Podobnie ENDreguła jest wykonywana tylko raz, po odczytaniu wszystkich danych wejściowych.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
diabelnie
źródło
7

awkprzetwarza każdy wiersz danych wejściowych dla wyrażeń podanych w treści innych niż BEGINi ENDbloki. W przypadku BEGINi ENDbloków, awkinstrukcje będą przetwarzane tylko raz, przed rozpoczęciem przetwarzania danych wejściowych i odpowiednio po przetworzeniu danych wejściowych. Bez tego BEGINbloku nie tylko nie byłbyś w stanie wydrukować jednorazowych informacji, takich jak nagłówki, ale nie byłbyś w stanie skutecznie zainicjować niektórych zmiennych wymaganych przez ciało. Ponadto, FYI, awkprogram może mieć wielokrotne BEGINi ENDbloków.

mkc
źródło
2

awkwykonuje każdy blok tylko wtedy, gdy wzorzec przed nim pasuje. Pusty wzór (tylko blok) pasuje do każdej linii. BEGINi ENDsą specjalnymi wzorami, które pasują do początku i końca pliku (analogicznie do znaczenia ^i $w kierunku poziomym).

Jeśli chcesz coś wykonać przed odczytaniem pliku, użyj BEGIN. Na przykład inicjalizacja liczników lub coś takiego. ENDmoże następnie zebrać wyniki.

orion
źródło
0

W podanym przykładzie, który moim zdaniem jest uproszczony dla jasności pedagogicznej, masz rację, że jest zbyteczny. Możesz uzyskać te same wyniki bez użycia BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

dałoby takie same wyniki, ponieważ instrukcja print jest ograniczona tylko do pierwszego wiersza danych wejściowych.

Biorąc to pod uwagę, bloki BEGINi ENDsą niezwykle potężnymi narzędziami. Jak wspomniano w innych rozwiązaniach, można użyć BEGINbloku do zainicjowania zmiennych lub innych procedur, które należy wykonać tylko raz, ale można go również użyć do uruchomienia poleceń Awk, gdy nie ma plików do przetworzenia. Prosty przykład:

BEGIN { print sqrt(12/4) }

Możesz zobaczyć poważniejszy przykład programowania w Awk bez przetwarzania jakichkolwiek danych tutaj .

Podobnie, ENDblok jest niezwykle przydatny do wykonywania obliczeń i podsumowywania wszystkich danych wejściowych. Nie można tego zrobić (zwykle) bez pierwszego odczytu wszystkich danych. Prosty przykład podsumowania danych wejściowych można znaleźć tutaj

myq
źródło