Кодировка файлов /proc//cmdline

Все другие решения здесь, скорее всего, не сработают на некоторых записях журнала, например. те, которые содержат пробелы внутри поля реферера или лишние кавычки и обратную косую черту, имена доменов в верхнем регистре, 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 | изображения | другие | под | домены) \.)? .

2
31.01.2016, 08:50
0 ответов

Теги

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