2013-09-25 4 views
1

Я хотел бы эффективно искать несколько сотен файлов журнала для ~ 200 имен файлов.Поиск нескольких сотен имен файлов в нескольких сотнях файлов журнала

Я легко могу это сделать, используя grep's -f и поместив иглу (и) в файл.

Однако есть несколько проблем:

  • Я заинтересован в эффективном делать это, как и в How to use grep efficiently?
  • Я хочу знать все матчи для каждый термин поиска (т.е. имя файла) во всех файлах журнала отдельно. grep -f будет соответствовать тому, как он находит иглы в каждом файле.
  • Я хотел бы знать, когда имя файла не сопоставляется нигде.

2,7 i7 MBP ж/16gb ОЗУ

Использование grep -ron -f needle * дает мне:

access_log-2013-01-01:88298:google 
access_log-2013-01-01:88304:google 
access_log-2013-01-01:88320:test 
access_log-2013-01-01:88336:google 
access_log-2013-01-02:396244:test 
access_log-2013-01-02:396256:google 
access_log-2013-01-02:396262:google 

где needle содержит:

google 
test 

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

+0

Укажите ли какое-либо из названий файлов пробелы? Кроме того, будут ли времена, когда имя файла добавляется к другому тексту или всегда будет разделяться пробелом/началом строки/конца строки? – Desidero

+0

Как выглядит вывод этого скрипта? – michael501

+0

@Desidero имена файлов не содержат пробелов. Имена файлов могут быть добавлены к другому тексту. Думайте /foor/bar/baz/needle.txt – kayaker243

ответ

1

Как насчет объединения grep и find в сценарии bash?

for needle in $(cat needles.txt); do 
    echo $needle 
    matches=$(find . -type f -exec grep -nH -e $needle {} +) 
    if [[ 0 == $? ]] ; then 
     if [[ -z "$matches" ]] ; then 
      echo "No matches found" 
     else 
      echo "$matches" 
     fi 
    else 
     echo "Search failed/no matches" 
    fi 
    echo 
done 

needles.txt содержит список ваших целевых файлов.

Для чтения игл (которые теперь могут содержать пробела) построчных строки из файла, используйте эту версию:

cat needles.txt | while read needle ; do 
    echo $needle 
    matches=$(find . -type f -exec grep -nH -e "$needle" {} +) 
    if [[ 0 == $? ]] ; then 
     if [[ -z "$matches" ]] ; then 
      echo "No matches found" 
     else 
      echo "$matches" 
     fi 
    else 
     echo "Search failed/no matches" 
    fi 
    echo 
done 

Если вы делаете комбинацию с xargs, кодом ошибки $? уже не равна нулю даже при успешном завершении. Это может быть менее безопасным, но работает для меня:

cat needles.txt | while read needle ; do 
    echo $needle 
    matches=$(find . -type f -print0 | xargs -0 -n1 -P2 grep -nH -e "$needle") 
    if [[ -z "$matches" ]] ; then 
     echo "No matches found" 
    else 
     echo "$matches" 
    fi 
    echo 
done 
+0

Спасибо! Я немного изменил его, чтобы использовать xargs для распространения grep в течение 8 процессов. 'matches = $ (find. -type f -print0 | xargs -0 -n1 -P8 grep -nH -E $ needle)'. Это работает. Однако оказывается, что мне нужно сопоставить пробелы - термин, который я хочу найти, - это фактически 'GET/term /'. Включая обратную косую черту перед тем, как истекает срок в файле needles.txt, кажется, что он завершает выполнение. Цитирование '$ needle', кажется, предотвращает оценку' $ needle'. Любое предложение? – kayaker243

+0

@ kayaker243 Можете ли вы адаптировать версию в редактировании к вашим потребностям? Спасибо, что указали на параллелизм с xargs, что является новым для меня. – rerx

+0

Нет, мои навыки bash не справляются с задачей иметь дело с пробелами в этом контексте :( – kayaker243

1

Чтобы определить, какие нет игл больше нет матчей, вы можете взять выход из Grep и:

  1. Использование AWK или что-то подобное, чтобы извлечь просто привязанные строки к отдельному файлу.
  2. Concatenate что иголки файл в этот файл
  3. ли sort --uniq filename -o temp1
  4. Соединить иглы файл в TEMP1
  5. ли sort temp1 -o temp2
  6. uniq -u temp2 > temp3

temp3 будет содержать иглы, которые больше не используются.

Возможно, существует более сжатый способ сделать это. Шаги с 1 по 3 получают список уникальных игл, найденных в файлах.

Произнесите файл иглы содержит:

google 
foo 
bar 

И Grep находит Foo и бар в нескольких файлах, но не находит Google. Шаг 1 создаст файл типа:

foo 
bar 
bar 
foo 
foo 
bar 
foo 

sort --uniq создаст:

foo 
bar 

конкатенации файл игл дает

foo 
bar 
google 
foo 
bar 

Сортировка дает:

bar 
bar 
foo 
foo 
google 

а также FINA l uniq -u команда выведет одну строку:

google 
Смежные вопросы