У меня тысячи лог-файлов - все очень большие. У одного из них будет IP-адрес, который я ищу. Я знаю, что это, скорее всего, произойдет в верхней части файла. Я могу сделать:

head -n 500 *.log | fgrep myip

И я увижу, что "да", это в одном из лог-файлов. Как определить какой? Выбрать полное содержимое (fgrep myip *.log) всех файлов невозможно из-за их размера.

0
Jeff Schaller 12 Июн 2018 в 02:29
IPv4 адрес???
 – 
Jeff Schaller
12 Июн 2018 в 02:29
Да, это адрес IPv4. Кто-нибудь использует что-то еще ;-)
 – 
PaulN
12 Июн 2018 в 04:57
Будьте осторожны с fgrep, ищущим 10.55.33.6, но совпадающим с 110.55.33.68.
 – 
roaima
12 Июн 2018 в 13:23

4 ответа

Лучший ответ

Нечто подобное должно помочь.

find . -iname "*.log" -print0 | xargs -0 -i{} bash -c 'echo "»»»File Name: {}«««"; head -n 500 {} | fgrep -B 501 myip'

Он создаст длинный список имен файлов, затем до 500 строк найденных данных, затем длинный список имен файлов. Имя файла, которое вам нужно, это то, которое находится непосредственно перед длинным списком данных.

0
ctrl-alt-delor 12 Июн 2018 в 01:25

Вы можете уйти только с awk:

awk -v ip=127.0.0.1 'substr($0, ip) > 0 {print FILENAME ": " $0} FNR > 500 {nextfile}' *.log

Если IP был найден в текущей строке, мы печатаем его и имя файла. Мы переходим к следующему файлу, если текущий номер строки для текущего файла (FNR) стал > 500.

1
muru 12 Июн 2018 в 12:35
find -name \*.log -print0 |
  xargs -0 sh -c 'for i; do head -n 500 $i | fgrep -q myip && echo $i; done

Это найдет все имена файлов, оканчивающиеся на .log, и передаст этот список в xargs. -print0 и xargs -0 обычно используются для использования нулевого байта для завершения имен файлов, чтобы защитить имена файлов, содержащие пробелы (нулевой байт никогда не может использоваться в имени файла, поэтому он является безопасным разделителем).

xargs запустит команду, указанную после xargs, и ее аргументы с таким количеством имен файлов, которое поместится за один вызов команды. В этом случае дана команда sh (оболочка), и этой оболочке дается небольшой сценарий оболочки для запуска.

Сценарий оболочки в основном:

for i; do
    head -n 500 $i | fgrep -q myip && echo $i
done

Часть for i перебирает все аргументы, переданные оболочке, то есть все имена файлов. Для каждого имени файла он берет первые 500 строк и ищет заданную строку. fgrep -q означает, что fgrep останавливается, как только строка найдена; если строка найдена, присваивается статус выхода «успех», в противном случае — «неудача». Наконец, && echo $i означает, что если предыдущая команда имеет статус «успешно», выполняется эхо, что означает, что имя файла отображается, если строка найдена.

0
wurtel 12 Июн 2018 в 12:16

Я бы:

  1. перебрать все файлы
  2. захватить первые 500 строк
  3. посмотрите, есть ли IP в этих строках
  4. если это так, напечатайте имя файла и завершите цикл

Как код:

for f in ./*
do 
  head -n 500 "$f" | grep -qF myip && { printf "Found in: $f"; break; }
done

Где вы замените myip на IP-адрес, который вы ищете. Вы можете создать функцию (или сценарий оболочки), которая принимает желаемый IP-адрес в качестве параметра для поиска:

findlogip ()
{
    for f in ./*;
    do
        head -n 500 "$f" | grep -qF "$1" && {
            printf "Found in: $f\n";
            break
        };
    done
}

Как прокомментировал roaima, вы можете быть осторожны с IP-адресом, который вы ищете, чтобы случайно не найти другой IP-адрес (10.55.33.6, но соответствующий 110.55.33.68 в примере). С помощью GNU grep (предполагается, учитывая тег ) , вы можете окружить данный IP-адрес маркерами \b:

...
head -n 500 "$f" | grep -q "\b$1\b" && ...
...

Вы отбрасываете параметр grep -F (фиксированная строка), поскольку выражение больше не является «фиксированным», а является регулярным выражением.

0
Jeff Schaller 13 Июн 2018 в 19:47