Эффективный метод для анализа большого количества файлов - PullRequest
0 голосов
/ 06 октября 2018

У меня есть входящие данные в диапазоне 130 ГБ - 300 ГБ, содержащие 1000 (возможно, миллионы) небольших .txt файлов размером 2 КБ - 1 МБ в ОДНОЙ папке.Я хочу их эффективно проанализировать.

Я смотрю на следующие варианты (по ссылке - 21209029 ]:

  1. Использование printf+ xargs (с последующей egrep & awk обработкой текста)

    printf '%s\0' *.txt | xargs -0 cat | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
    
  2. с использованием find + cat (с последующим egrep & awkобработка текста)

    find . -name \*.txt -exec cat {} > all_in_1.tmp \;
    cat all_in_1.tmp | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
    
  3. Использование for loop

    for file in *.txt
    do
      cat "$file" | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' >> all_in_1.out
    done
    

Какой из перечисленных вариантов наиболее эффективен?лучший способ сделать это?

Или использование команд оболочки вообще не рекомендуется для обработки такого объема данных (я предпочитаю способ оболочки для этого)?

На сервере установлен RHEL6,5 ОС с 32 ГБ памяти с 16 ядрами (@ 2,2 ГГц).

1 Ответ

0 голосов
/ 06 октября 2018

Подходы 1 и 3 расширяют список файлов в командной строке оболочки.Это не будет работать с огромным количеством файлов.Подходы 1 и 3 также не работают, если файлы распределены по многим каталогам (что, вероятно, с миллионами файлов).

Подход 2 делает копию всех данных, поэтому он также неэффективен.

Вы должны использовать find и передавать имена файлов непосредственно в egrep.Используйте параметр -h, чтобы подавить префикс с именем файла:

find . -name \*.txt -print0 \
 | xargs -0 egrep -i -v -h 'pattern1|...|pattern8' \
 | awk '{gsub(/"\t",",")}1' > all_in_1.out

xargs автоматически запустит несколько процессов egrep в последовательности, чтобы избежать превышения лимита командной строки в одном вызове.

В зависимости от содержимого файла также может быть более эффективным избегать процессов egrep в целом и выполнять фильтрацию непосредственно в awk:

find . -name \*.txt -print0 \
 | xargs -0 awk 'BEGIN { IGNORECASE = 1 } ! /pattern1|...|pattern8/ {gsub(/"\t",",")}1' > all_in_1.out

BEGIN { IGNORECASE = 1 } соответствуетопция -i, равная egrep, и ! инвертирует смысл сопоставления, как и -v.IGNORECASE представляется расширением GNU.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...