2013-12-17 13 views
36

Próbuję uruchomić polecenie powłoki z poziomu awk dla każdego wiersza pliku, a polecenie powłoki wymaga jednego argumentu wejściowego. Próbowałem użyć system(), ale nie rozpoznałem argumentu wejściowego.Jak przekazać zmienne z awk do polecenia powłoki?

Każda linia tego pliku jest adresem pliku i chcę uruchomić polecenie, aby przetworzyć ten plik. Tak więc, dla prostego przykładu, chcę użyć polecenia "wc" dla każdej linii i przekazać $1 do wc.

awk '{system("wc $1")}' myfile 
+0

Wyszukiwanie w pierwszej kolejności, istnieje już sto rozwiązań. – BMW

+2

Dlaczego Twoim zdaniem awk jest odpowiednim narzędziem do tej pracy? Wydaje się, że 'xargs' lub prosta powłoka' while read line' pętli będzie lepsza i łatwiejsza. –

+1

Po drugiej stronie: dlaczego uważasz, że WC jest właściwym narzędziem do tej pracy? Wygląda na to, że zmienne wbudowane awk i funkcje byłyby lepsze i łatwiejsze? –

Odpowiedz

49

jesteś blisko. trzeba złączyć z wiersza poleceń z zmiennych awk:

awk '{system("wc "$1)}' myfile 
+0

dzięki, to działa! ale jeszcze jedno pytanie? Czy możemy przypisać wyjście do nowej zmiennej? –

+0

tak, możemy. '{newVar = system (...)}' @VahidMir – Kent

+5

To jest zła składnia dla tego zadania, jest to zła aplikacja dla systemu(), druk nie robi tego, co myślisz, że to zrobi, i nie, nie możesz przypisz wynik wywołania system() do zmiennej awk, to, co napisałeś w swoim komentarzu, przypisuje kod powrotu z system() do zmiennej. Czas na kawę @Kent! –

34

Nie można chwycić wyjście z awk system() połączenia można uzyskać tylko status wyjścia. Użyj getline/pipe lub getline/variable/pipe konstrukty

awk '{ 
    cmd = "your_command " $1 
    while (cmd | getline line) { 
     do_something_with(line) 
    } 
    close(cmd) 
}' file 
+3

+1 dla poprawnego sposobu uzyskania wyniku polecenia powłoki, ale ogólnie składnia do utworzenia zmiennej to 'cmd =" ​​twoja_polecenie \ "" $ 1 "" \ ", więc argument jest cytowany, gdy jest wykonywane cmd i musisz sprawdzić, czy wynik getline jest większy od zera, czy utkniesz w nieskończonej pętli, jeśli się nie powiedzie. –

+1

+1. OP, jeśli potrzebujesz zapisać wynik w var, również przyjmij tę odpowiedź. mój nie był poprawny dla przypisania var. – Kent

2

FYI oto jak używać awk przetwarzać pliki, których nazwy są przechowywane w pliku (zapewniając WC jak funkcjonalność w tym przykładzie):

gawk ' 
NR==FNR { ARGV[ARGC++]=$0; next } 
{ nW+=NF; nC+=(length($0) + 1) } 
ENDFILE { print FILENAME, FNR, nW, nC; nW=nC=0 } 
' file 

powyższych zastosowań GNU awk dla ENDFILE. Z innymi awkami przechowuj tylko wartości w tablicy i drukuj w pętli w sekcji END.

0

Albo użyć rury | jak w bash następnie sprowadzaniu wyjście w zmiennej z awk getline, jak to

zcat /var/log/fail2ban.log* | gawk '/.*Ban.*/ {print $7};' | sort | uniq -c | sort | gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}' 

tej linii będzie drukować wszystkie zakazanych adresów IP z serwera wraz z ich pochodzenia (kraj) przy użyciu pakietu geoip-bin.

Ostatnia część tego jednego-liner jest ten, który dotyczy nas:

gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}' 

To po prostu mówi: uruchom polecenie "geoiplookup 182.193.192.4 | -f2 -d:" ($ 2 zostaje podstawiona, jak można się domyślić) i umieścić wynik tego polecenia w geoip (bit | getline geoip). Następnie wydrukuj coś i coś wewnątrz zmiennej geoip.

Pełny przykład i wyniki można znaleźć here, artykuł napisałem.

Powiązane problemy