2012-06-10 9 views
8

Chcę uzyskać zapytania "GET" z moich dzienników serwera.Używanie grep do uzyskania następnego WORD po meczu w każdej linii

Na przykład, jest to log serwera

1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] code 404, message File not fo$ 
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 - 
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] code 404, message File not fo$ 
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 - 

Kiedy próbuję z prostego grep lub awk

Adi:~ adi$ awk '/GET/, /HTTP/' serverlogs.txt 

daje się

1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 - 
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 - 

po prostu chcę, aby wyświetlić : hello i ss

Czy jest to możliwe?

Odpowiedz

8

zakładając, że masz do GNU grep, można użyć stylu Perl regex zrobić pozytywny lookbehind:

grep -oP '(?<=GET\s/)\w+' file 

Jeśli nie masz gnu grep, to radzę po prostu za pomocą sed:

sed -n '/^.*GET[[:space:]]\{1,\}\/\([-_[:alnum:]]\{1,\}\).*$/s//\1/p' file 

Jeśli zdarzy się, że GNU sed (co byłoby dziwne, jeśli nie masz gnu grep ale mam GNU sed), które mogą być znacznie uproszczone:

sed -n '/^.*GET\s\+\/\(\w\+\).*$/s//\1/p' file 

Najważniejsze jest to, że na pewno nie potrzebujesz do tego rur. Wystarczy tylko grep lub sed.

+0

Awesome. Działa świetnie!! Krótkie i proste. –

5

W tym przypadku, ponieważ plik dziennika ma znaną strukturę, jedną z opcji jest użycie cut do wyciągnięcia 7. kolumny (pola są domyślnie oznaczone tabulatorami).

grep GET log.txt | cut -f 7 
+0

Ciągle pokazuję całą linię. 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "POBIERZ/cześć HTTP/1.1" 404 - 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET/ss HTTP/1.1" 404 - –

+0

Hmmm, czy jest oddzielony spacją lub tabulatorami? Jeśli spacja, użyj '-d ''' with cut, aby określić spację jako ogranicznik kolumny. –

+0

Działa wspaniale z parametrem ** - d '' **. –

1

Często łatwiej jest użyć potoku zamiast pojedynczego złożonego wyrażenia regularnego. To działa na danych podałeś:

fgrep GET /tmp/foo | 
    egrep -o 'GET (.*) HTTP' | 
    sed -r 's/^GET \/(.+) HTTP/\1/' 

Rurociąg ten zwraca następujące wyniki:

hello 
ss 

pewnością istnieją inne sposoby, aby otrzymać pracę, ale to ewidentnie działa na dostarczonych korpusie.

2

użyciu rury przypadku korzystania grepa:

grep -o /he.* log.txt | grep -o [^/].* 
grep -o /ss log.txt | grep -o [^/].* 

[^ /] oznacza wyciąg litery po^symbol z wyjścia grep

0
gawk '{match($7,/\/(\w+)/,a);} length(a[1]){print a[1]}' log.txt 
hello 
ss 

Jeśli gawk następnie powyżej polecenia użyje match służy do wybierania pożądanej wartości za pomocą wyrażeń regularnych i zapisywania jej w tablicy a.

0

starałem się to zrobić i natknąłem się na ten link: https://www.unix.com/shell-programming-and-scripting/153101-print-next-word-after-found-pattern.html

Podsumowanie: wykorzystania grep, aby znaleźć pasujące wiersze, a następnie użyć awk, aby znaleźć wzór i wydrukować następne pole:

grep pattern logfile | \ 
    awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}' 

Jeśli chcesz poznać niepowtarzalne zdarzenia:

grep pattern logfile | \ 
    awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}' | \ 
    sort | \ 
    uniq -c 
Powiązane problemy