Использование grep для получения следующего слова после совпадения в каждой строке
Я хочу получить "GET" запросы из журналов моего сервера.
например, это журнал сервера
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 -
когда я пытаюсь с простым grep или awk,
Adi:~ adi$ awk '/GET/, /HTTP/' serverlogs.txt
выдает
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 -
Я просто хочу, чтобы отобразить : привет и ss
есть ли способ сделать это?
6 ответов
предполагая, что у вас есть gnu grep, вы можете использовать регулярное выражение в стиле perl для позитивного поиска:
grep -oP '(?<=GET\s/)\w+' file
если у вас нет gnu grep, то я бы посоветовал просто использовать sed:
sed -n '/^.*GET[[:space:]]\{1,\}\/\([-_[:alnum:]]\{1,\}\).*$/s///p' file
если у вас есть gnu sed, это может быть значительно упрощено:
sed -n '/^.*GET\s\+\/\(\w\+\).*$/s///p' file
суть здесь в том, что вам, конечно, не нужны трубы для этого. grep
или sed
одного будет достаточно.
в этом случае, поскольку файл журнала имеет известную структуру, один из вариантов-использовать cut
чтобы вытащить 7-й столбец (поля по умолчанию обозначаются вкладками).
grep GET log.txt | cut -f 7
используйте трубу, если вы используете grep:
grep -o /he.* log.txt | grep -o [^/].*
grep -o /ss log.txt | grep -o [^/].*
[^ / ] означает извлечение букв после символа ^ из вывода grep
Я пытался сделать это, и наткнулся на эту ссылку: https://www.unix.com/shell-programming-and-scripting/153101-print-next-word-after-found-pattern.html
резюме: используйте grep для поиска совпадающих строк, затем используйте awk для поиска шаблона и печати следующего поля:
grep pattern logfile | \
awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}'
Если вы хотите знать уникальные вхождения:
grep pattern logfile | \
awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}' | \
sort | \
uniq -c
часто проще использовать конвейер, а не одно сложное регулярное выражение. Это работает на данных, которые вы предоставили:
fgrep GET /tmp/foo |
egrep -o 'GET (.*) HTTP' |
sed -r 's/^GET \/(.+) HTTP//'
этот конвейер возвращает следующие результаты:
hello
ss
есть, конечно, другие способы выполнить работу, но это явно работает на предоставленном корпусе.
gawk '{match(,/\/(\w+)/,a);} length(a[1]){print a[1]}' log.txt
hello
ss
если у вас gawk
затем выше команда будет использовать match
функция для выбора желаемого значения с помощью regex и сохранения его в массив a
.