Получение строки запроса из URL в файле журнала

Если вы не укажете явную опцию -o , по умолчанию должен быть файл с именем a.out . На странице руководства по компилятору GNU man gcc это объясняется следующим образом:


-o file
    Place output in file file.  This applies to whatever sort of output
    is being produced, whether it be an executable file, an object
    file, an assembler file or preprocessed C code.

    If -o is not specified, the default is to put an executable file in
    a.out, the object file for source.suffix in source.o, its assembler
    file in source.s, a precompiled header file in source.suffix.gch,
    and all preprocessed C source on standard output.
4
15.11.2016, 02:11
5 ответов

Вот довольно читаемый подход sed

$ cat log.txt | grep "http://www.google.com/search?" | sed  s/^.*search?// | sed s/\"\;.*//

т.е.

Удалите начало строки с помощью:

s/   # replace a match which is:
  ^       # from the start of the line
  .*      # any number of any characters
  search? # the text "search?"
//   # with nothing (remove it)

, затем удалите конец строки с помощью

s/    # replace a match which is:
  \"    # a double quote (escaped with backslash)
  \;    # a semicolon (escaped with backslash)
  .*    # any number of characters
//    # with nothing (remove it)

, оставив только параметры

1
27.01.2020, 20:49
awk -F"[?|;]" '/google.com\/search/{print $2}' log.txt

awk -F? '/google.com\/search/{gsub(";.*","",$2);print $2}' log.txt
0
27.01.2020, 20:49

общая версия

awk '$11 ~ /?/ { printf "%s\n",substr($11,1+index($11,"?")) ;}'

где

  • $11 ~ /\?/ поиск ? в URL
  • substr($11,1+index($11,"?") поиск части после ?
  • обратите внимание, что аргумент не разбирается.
  • это не приведет к разбору URL (например, пробел будет показан как %20 )

предыдущая версия

awk '$11 ~ /http:\/\/www.google.com\/search?/ { print substr($11,26) ;}' 

где

  • $11 - номер поля, содержащего ссылку, возможно, потребуется корректировка
  • 28 - длина "http://www.google.com/search?"
3
27.01.2020, 20:49

Все другие решения здесь, скорее всего, не сработают на некоторых записях журнала, например. те, которые содержат пробелы внутри поля реферера или лишние кавычки и обратную косую черту, имена доменов в верхнем регистре, https вместо http или ключевые слова внутри поля местоположения, а также поля реферера.

Например:

1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /a b/ HTTP/1.0" 200 0 "http://www.google.com/search?..." "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /i/love/http://www.google.com/search?ing HTTP/1.0" 200 0 "http://www.google.com/search?..." "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET / HTTP/1.0" 200 0 "http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /nohttpver" 200 0 "http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /" 200 0 "http://example.org/http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /" 200 0 "http://WWW.GOOGLE.COM/search?spaces in referrer" "Mozilla/4.0"

Чтобы справиться с этим, нам сначала нужно правильно извлечь второе поле в двойных кавычках . Обратите внимание, что в файлах журнала Apache используется обратная косая черта, чтобы избежать лишних кавычек или других специальных символов. Это означает, что наивные регулярные выражения, такие как "[^"] * ", недостаточно хороши.

Использование grep для извлечения поля реферера (второе поле в двойных кавычках):

grep -oP '^[^"]+"[^"\\]*(?:\\.[^"\\]*)*"[^"]+"\K[^"\\]*(?:\\.[^"\\]*)*(?=")' logfile.txt

Выглядит безумно! Разберем его:

  • Аргумент o для grep означает, что мы просто получаем совпадающую часть строки, а не остальную часть
  • P аргумент grep указывает ему использовать Perl-совместимые регулярные выражения
  • Общая структура используемого здесь регулярного выражения, ... \ K ... (? = .. .) означает, что мы проверяем весь шаблон, но будут выведены только вещи между \ K и (? = ...)

. регулярное выражение вниз:

  1. ^ [^ "] + - Получить все, что находится между началом строки и первым "
  2. "[^" \\] * (?: \\. [^ "\\] *) *" - Получить всю первую строку в двойных кавычках.См. Этот ответ https://stackoverflow.com/a/5696141/1764245
  3. [^ "] + - Получите все, что находится между двумя strings
  4. "\ K [^" \\] * (?: \\. [^ "\\] *) * (? =") То же, что и выше, но у нас есть \ K после первого « для начала сопоставления данных после этого и (? =") для прекращения сопоставления данных перед последним ».

После этого будет намного проще обрабатывать данные, потому что вам больше не придется беспокоиться о кавычках и правильном извлечении поля из файла журнала.

Например, вы можете перенаправить вывод в другой grep:

grep -oP ... logfile.txt | grep -oPi '^https?://www\.google\.com/search\?\K.*'

Здесь параметр i для второго grep делает его нечувствительным к регистру.

В качестве альтернативы вы можете добавить проверку начала реферера google.com непосредственно в первое регулярное выражение и переместить \ K соответствующим образом, но я бы рекомендовал против этого, поскольку лучше запускать два регулярных выражения, которые выполняют одну работу и делают ее хорошо, чем объединять их в одно, где его задача не ясна.

Обратите внимание, что если вы хотите собирать источники перехода из других доменов Google, вам нужно будет немного изменить свое регулярное выражение. Google владеет множеством поисковых доменов .

Если вы не возражаете против того, чтобы потенциально поймать несколько сайтов, не принадлежащих Google, вы можете сделать:

... | grep -oPi '^https?://(www\.)?google\.[a-z]{2,3}(\.[a-z]{2})?/search\?\K.*'

В противном случае вам нужно будет попытаться сопоставить только поисковые домены, принадлежащие Google, которые являются постоянно меняющейся целью:

... | grep -oPi '^https?://(www\.)?google\.(a[cdelmstz]|b[aefgijsty]|cat|c[acdfghilmnvz]|co\.(ao|bw|c[kr]|i[dln]|jp|k[er]|ls|m[az]|nz|t[hz]|u[gkz]|v[ei]|z[amw])|com(\.(a[fgiru]|b[dhnorz]|c[ouy]|do|e[cgt]|fj|g[hit]|hk|jm|k[hw]|l[bcy]|m[mtxy]|n[afgip]|om|p[aeghkry]|qa|s[abglv]|t[jrw]|u[ay]|v[cn]))?|d[ejkmz]|e[es]|f[imr]|g[aefglmpry]|h[nrtu]|i[emoqst]|j[eo]|k[giz]|l[aiktuv]|m[degklnsuvw]|n[eloru]|p[lnst]|r[osuw]|s[cehikmnort]|t[dgklmnot]|us|v[gu]|ws)/search\?\K.*'

Также обратите внимание, что если вы хотите включить поиск изображений Google и другие поддомены поиска, вам нужно будет изменить (www \.)? в одной из приведенных выше команд grep на что-то вроде ((www | изображения | другие | под | домены) \.)? .

4
27.01.2020, 20:49

Думаю, я понял это.

grep "http://www.google.com/search?" logs.txt | cut -d" " -f11 |  sed -r 's/^.{30}//'

Кажется ли это приемлемым решением?

0
27.01.2020, 20:49

Теги

Похожие вопросы