Grep огромное количество шаблонов из огромного файла

Хинду поддерживает ARMv4 или позже по крайней мере с 32 МБ.

  1. Откройте свой нетбук и удостоверьтесь, что Ваша NAND на 2 ГБ SSD не является просто микросхемой, но и чем-то с IDE или SATA.
  2. Подключите ssd к компьютеру с нормальной ОС и сделайте изображение Вашего Windows CE (использующий dd ;) таким образом, можно играть с ним позже.
  3. Установите хинду сначала в Qemu (qemu-system-arm).
  4. Сделайте изображение установленного хинду.
  5. Разверните хинду изображение на ssd.
  6. ...
  7. Получите прибыль!

Я желаю Вам удачи.

18
01.01.2017, 11:33
11 ответов

Этот ответ на основе awk ответ отправляется potong..
Это дважды с такой скоростью, как comm метод (в моей системе), для тех же 6 миллионов строк в основном файле и 10 тысяч ключей... (теперь обновленный для использования FNR, НОМЕРА)

Хотя awk быстрее, чем Ваша существующая система и даст Вам и Вашему компьютеру (компьютерам) некоторую передышку, знать, что, когда обработка данных так интенсивна, как Вы описали, Вы получите лучше всего полные результаты путем переключения на специализированную базу данных; например, SQlite, MySQL...


awk '{ if (/^[^0-9]/) { next }              # Skip lines which do not hold key values
       if (FNR==NR) { main[$0]=1 }          # Process keys from file "mainfile"
       else if (main[$0]==0) { keys[$0]=1 } # Process keys from file "keys"
     } END { for(key in keys) print key }' \
       "mainfile" "keys" >"keys.not-in-main"

# For 6 million lines in "mainfile" and 10 thousand keys in "keys"

# The awk  method
# time:
#   real    0m14.495s
#   user    0m14.457s
#   sys     0m0.044s

# The comm  method
# time:
#   real    0m27.976s
#   user    0m28.046s
#   sys     0m0.104s

11
27.01.2020, 19:45
  • 1
    Это быстро, но я не понимаю большую часть awk: на что должны быть похожими имена файлов? Я попробовал file1 -> mainfile и file2 -> keys с простофилей и mawk, и это производит неправильные ключи. –  Teresa e Junior 22.01.2012, 08:39
  • 2
    file1 имеет ключи, имена и задания. –  Teresa e Junior 22.01.2012, 08:41
  • 3
    'mainfile' является большим файлом (с ключами, именами и заданиями). Я только что назвал его "mainfile', потому что я продолжал перепутываться, которым файл был который (file1 по сравнению с file2).. 'ключи' содержат только эти 10 тысяч, или однако многих, ключи.. Поскольку Ваша ситуация НЕ перенаправляет, что-либо... просто использует file1 EOF file2, Они - названия Ваших файлов.." EOF "является файлом с 1 строкой creadte сценарием для указания на конец первого файла (основной файл данных) и запуск второго файла (ключи). awk позвольте Вам читать в серии файлов.. В этом случае тот ряд имеет 3 файла в нем. Вывод переходит в stdout –  Peter.O 22.01.2012, 09:40
  • 4
    Этот сценарий распечатает любые ключи, которые присутствуют в mainfile, И это также распечатает любые ключи от keys файл, которые НЕ находятся в mainfile... Это, вероятно, что происходит... (Я немного далее изучу его... –  Peter.O 22.01.2012, 10:01
  • 5
    Спасибо, @Peter. O! Так как файлы являются конфиденциальными, я пытаюсь создать файлы примера с $RANDOM для загрузки. –  Teresa e Junior 22.01.2012, 10:38

Проблема, конечно, состоит в том, что Вы выполняете grep на больших временах файла 10,000. Необходимо считать оба файла только однажды. Если Вы хотите остаться вне языков сценариев, можно сделать это этот путь:

  1. Извлеките все числа из файла 1 и отсортируйте их
  2. Извлеките все числа из файла 2 и отсортируйте их
  3. Выполненный comm в отсортированных списках для получения, что находится только во втором списке

Что-то вроде этого:

$ grep -o '^[0-9]\{12\}$' file1 | sort -u -o file1.sorted
$ grep -o  '[0-9]\{12\}'  file2 | sort -u -o file2.sorted
$ comm -13 file1.sorted file2.sorted > file3

Посмотрите man comm.

Если Вы могли бы усекать большой файл каждый день (как файл журнала), Вы могли бы сохранить кэш отсортированных чисел и не должны будете анализировать его целый каждый раз.

16
27.01.2020, 19:45
  • 1
    Аккуратный! 2 секунды (на не особенно быстро управляет) с 200 000 случайных записей строк в mainfile (т.е. 600 000 строк) и 143 000 случайных ключей (это, как мои данные тестирования закончились)... протестированный, и они работают (но Вы знали это :)... Я действительно задаюсь вопросом о {12}.. OP использовала 12, но ключи в качестве примера равняются 13 длинному... –  Peter.O 21.01.2012, 17:20
  • 2
    Просто немного примечания, можно сделать это, не имея дело с временными файлами при помощи <(grep...sort) где имена файлов. –  Kevin 21.01.2012, 19:20
  • 3
    Спасибо, но захват и сортировка файлов берут намного дольше, чем мой предыдущий цикл (+2min).. –  Teresa e Junior 21.01.2012, 21:36
  • 4
    @Teresa e Junior. Насколько большой Ваш основной файл?... Вы упомянули, что это растет на 200 000 строк в день, но не, насколько большой это... Для сокращения объема данных Вы урожденная для обработки можно считать просто 200 000 строк текущих дней путем обращения внимания на последний номер строки, обработанный (вчера) и использование tail -n +$linenum производить только последние данные. Тем путем Вы будете обрабатывать только приблизительно 200 000 строк каждый день.. Я просто протестировал его с 6 миллионами строк в основном файле и 10 тысячами ключей... время: реальный 0m0.016s, пользователь 0m0.008s, sys 0m0.008s –  Peter.O 21.01.2012, 21:56
  • 5
    я являюсь действительно довольно озадаченным/любопытным о том, как Вы можете grep Ваши основные времена файла 10,000 и находить его быстрее, чем этот метод, который только захватывает его однажды (и однажды для намного меньшего file1)... Даже если Ваш вид занимает больше времени, чем мой тест, я просто не могу получить голову вокруг идеи, что чтение большого файла, который много раз не перевешивает единственный вид (timewise) –  Peter.O 21.01.2012, 22:16

Да, определенно используйте базу данных. Они сделаны точно для задач как это.

8
27.01.2020, 19:45
  • 1
    Спасибо! у меня нет большого опыта с базами данных. Какую базу данных Вы рекомендуете? У меня есть MySQL и установленная команда sqlite3. –  Teresa e Junior 21.01.2012, 11:47
  • 2
    Они и прекрасны для этого, sqlite более прост, потому что это - в основном просто файл и API SQL для доступа к нему. С MySQL необходимо настроить сервер MySQL для использования его. В то время как это не очень трудно также, sqlite мог бы быть лучшим для запуска с. –  Mika Fischer 21.01.2012, 16:07

С так большим количеством данных необходимо действительно переключиться на базу данных. Тем временем одна вещь, которую необходимо сделать для получения в какой-либо степени достойной производительности, не состоит в том, чтобы искать file1 отдельно для каждого ключа. Выполните сингл grep извлечь все неисключенные ключи сразу. Начиная с этого grep также строки возвратов, которые не содержат ключ, фильтруют их далеко.

grep -o '[0-9]\{12\}' file2 |
grep -Fxv -f - file1 |
grep -vx '[0-9]\{12\}' >file3

(-Fx средства искать целые строки, буквально. -f - средства прочитать список шаблонов от стандартного входа.)

2
27.01.2020, 19:45
  • 1
    , Если я не ошибаюсь, это не решает проблему хранения ключей, которые не находятся в большом файле, это сохранит ключи, которые находятся в нем. –  Kevin 21.01.2012, 19:15
  • 2
    @Kevin точно, и это вынудило меня использовать цикл. –  Teresa e Junior 21.01.2012, 20:07
  • 3
    @TeresaeJunior: добавление -v (-Fxv) может заботиться об этом. –  Paused until further notice. 21.01.2012, 20:28
  • 4
    @DennisWilliamson, Который выбрал бы все строки в большом файле, которые не соответствуют никому в файле ключей, включая имена, задания, и т.д. –  Kevin 22.01.2012, 05:26
  • 5
    @Kevin Благодарит, я неправильно читал вопрос. Я добавил фильтр для неключевых строк, хотя мое предпочтение теперь переходит к использованию comm. –  Gilles 'SO- stop being evil' 22.01.2012, 21:12

Разрешите мне укреплять то, что сказали другие, "Получите тебя к базе данных!"

Существуют двоичные файлы MySQL, в свободном доступе для большинства платформ.

Почему не SQLite? Это основано на памяти, загружая плоский файл при запуске его, затем закрывая его, когда Вы сделаны. Это означает, что, если Ваши компьютерные катастрофические отказы или процесс SQLite уходит, все данные - также.

Ваша проблема похожа просто на пару строк SQL и будет работать в миллисекундах!

После установки MySQL (который я рекомендую по другому выбору), я вышел бы из оболочки 40$ для Поваренной книги SQL O'Reilly Anthony Molinaro, который имеет много проблемных шаблонов, начиная с простого SELECT * FROM table запросы и прохождение через агрегируются и несколько соединений.

2
27.01.2020, 19:45
  • 1
    Да, я начну перемещать свои данные в SQL через несколько дней, спасибо! awk сценарии помогали мне много, пока я не сделал все это, хотя! –  Teresa e Junior 27.01.2012, 09:59

Я не уверен, является ли это точным выводом, который Вы ищете, но вероятно самый легкий путь:

grep -o '[0-9]\{12\}' file2 | sed 's/.*/^&$/' > /tmp/numpatterns.grep
grep -vf /tmp/numpatterns.grep file1 > file3
rm -f /tmp/numpatterns.grep

Вы могли также использовать:

sed -ne '/.*\([0-9]\{12\}.*/^\1$/p' file2 > /tmp/numpatterns.grep
grep -vf /tmp/numpatterns.grep file1 > file3
rm -f /tmp/numpatterns.grep

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

1
27.01.2020, 19:45
  • 1
    я верю этому также, находит числа, которые находятся в большом файле, не тех, которые не являются. –  Kevin 21.01.2012, 19:22
  • 2
    Корректный, я не видел!'' в OP. Просто должен использовать grep -vf вместо grep -f. –  Arcege 21.01.2012, 19:40
  • 3
    Никакой @arcege, grep - VF не отобразит ключи, не подобранные, он отобразит все включая имена и задания. –  Teresa e Junior 21.01.2012, 20:11

Я полностью соглашаюсь с Вами получающий базу данных (MySQL довольно прост в использовании). Пока Вы не получаете то выполнение, мне нравится Angus comm решение, но столько людей пробует grep и получая его неправильно, что я думал, что покажу (или по крайней мере один) корректный способ сделать это с grep.

grep -o '[0-9]\{12\}' keyfile | grep -v -f <(grep -o '^[0-9]\{12\}' bigfile) 

Первое grep получает ключи. Третье grep<(...)) берет все ключи, используемые в большом файле, и <(...) передачи это как файл как аргумент -f во втором grep. Это вызывает второе grep использовать его в качестве списка строк для соответствия. Это затем использует это для соответствия его входу (список ключей) от канала (сначала grep), и печать любые ключи, извлеченные из файла ключей и не (-v) большой файл.

Конечно, можно сделать это с временными файлами, которые необходимо отслеживать и не забыть удалять:

grep -o '[0-9]\{12\}'  keyfile >allkeys
grep -o '^[0-9]\{12\}' bigfile >usedkeys
grep -v -f usedkeys allkeys

Это печатает все строки в allkeys это не появляется в usedkeys.

1
27.01.2020, 19:45
  • 1
    К сожалению, это медленно, и я получаю ошибку памяти после 40 секунд: grep: Memory exhausted –  Peter.O 22.01.2012, 06:59
  • 2
    @Peter. O, Но это корректно. Так или иначе вот почему я предложил бы базу данных или comm, в том порядке. –  Kevin 22.01.2012, 07:43
  • 3
    Да, который работает, но намного медленнее, чем цикл. –  Teresa e Junior 22.01.2012, 08:43

Это могло бы работать на Вас:

 awk '/^[0-9]/{a[$0]++}END{for(x in a)if(a[x]==1)print x}' file{1,2} >file3

Править:

Исправленный сценарий для обеспечения дубликатов и неизвестных ключей в обоих файлах, все еще производит ключи из первого файла, не существующего во втором:

 awk '/^[0-9]/{if(FNR==NR){a[$0]=1;next};if($0 in a){a[$0]=2}}END{for(x in a)if(a[x]==1)print x}' file{1,2} >file3
3
27.01.2020, 19:45
  • 1
    , Это пропустит новые ключи, которые происходят несколько раз в основном файле (и в этом отношении, которые происходят несколько раз в файле ключей) Это, кажется, требует, чтобы постепенному увеличению количества массива основного файла не позволяли превысить 1, или некоторое эквивалентное обходное решение (+1, потому что это достаточно близко к метке), –  Peter.O 22.01.2012, 06:40
  • 2
    , который я попробовал простофилей и mawk, и он производит неправильные ключи... –  Teresa e Junior 22.01.2012, 08:42
  • 3
    @Peter. O я предположил, что основной файл имел уникальные ключи, и тот файл 2 был подмножеством основного файла. –  potong 22.01.2012, 17:11
  • 4
    @potong второй работает хороший и очень быстрый!Спасибо! –  Teresa e Junior 22.01.2012, 18:55
  • 5
    @Teresa e - Вы уверенный, что это работает правильно все же?.. Используя данные тестирования Вы, если, который должен произвести 5 000 ключей, когда я выполняю их, они производят 136 703 ключа, когда я добрался, пока я наконец не понял то, чем Ваши требования были... @potong, Конечно! FNR == НОМЕР (я никогда не использовал его перед :) –  Peter.O 23.01.2012, 00:17

Файл ключей не изменяется? Затем необходимо постараться не искать старые записи снова и снова.

С tail -f можно получить вывод растущего файла.

tail -f growingfile | grep -f keyfile 

grep-f читает шаблоны из файла, одна строка как шаблон.

1
27.01.2020, 19:45
  • 1
    Это было бы хорошо, но файл ключей всегда отличается. –  Teresa e Junior 22.01.2012, 19:49

Движение не должно было отправлять мой ответ, потому что я думал, что такой объем данных не должен быть обработан со сценарием оболочки, и правильный ответ для использования базы данных был уже дан. Но с тех пор теперь существует 7 других подходов...

Читает первый файл в памяти, затем захватывает второй файл для чисел и проверок, если значения хранятся в памяти. Это должно быть быстрее, чем несколько greps, если у Вас есть достаточно памяти для загрузки целого файла, который является.

declare -a record
while read key
do
    read name
    read job
    record[$key]="$name:$job"
done < file1

for number in $(grep -o '[0-9]\{12\}' file2)
do
    [[ -n ${mylist[$number]} ]] || echo $number >> file3
done
1
27.01.2020, 19:45
  • 1
    у меня есть достаточно памяти, но я нашел этого еще медленнее. Спасибо, хотя! –  Teresa e Junior 22.01.2012, 22:05

Я соглашаюсь с @jan-steinman, что необходимо использовать базу данных для этого вида задачи. Существует много способов взломать вместе решение со сценарием оболочки, поскольку другие ответы показывают, но выполнение его, что путь приведет к большому страданию, если Вы соберетесь использовать и поддержать код в течение какого-либо отрезка времени больше, чем просто однодневный одноразовый проект.

Принятию Вы находитесь на поле Linux затем Вы, скорее всего, установили Python по умолчанию, который включает sqlite3 библиотеку с Python v2.5. Можно проверить версию Python с:

% python -V
Python 2.7.2+

Я рекомендую пользоваться sqlite3 библиотекой, потому что это - простое основанное на файле решение, которое существует для всех платформ (включая внутреннюю часть Ваш веб-браузер!) и это не требует, чтобы сервер был установлен. По существу нулевая конфигурация и нулевое обслуживание.

Ниже простой сценарий Python, который проанализирует формат файла, который Вы дали как пример и затем делаете простой "выбор весь" запрос и производите все, что он сохранил в дб.

#!/usr/bin/env python

import sqlite3
import sys

dbname = '/tmp/simple.db'
filename = '/tmp/input.txt'
with sqlite3.connect(dbname) as conn:
    conn.execute('''create table if not exists people (key integer primary key, name text, job text)''')
    with open(filename) as f:
        for key in f:
            key = key.strip()
            name = f.next().strip()
            job = f.next().strip()
            try:
                conn.execute('''insert into people values (?,?,?)''', (key, name, job))
            except sqlite3.IntegrityError:
                sys.stderr.write('record already exists: %s, %s, %s\n' % (key, name, job))
    cur = conn.cursor()

    # get all people
    cur.execute('''select * from people''')
    for row in cur:
        print row

    # get just two specific people
    person_list = [1358726575123, 9973834728345]
    cur.execute('''select * from people where key in (?,?)''', person_list)
    for row in cur:
        print row

    # a more general way to get however many people are in the list
    person_list = [1358726575123, 9973834728345]
    template = ','.join(['?'] * len(person_list))
    cur.execute('''select * from people where key in (%s)''' % (template), person_list)
    for row in cur:
        print row

Да, это означает, что необходимо будет изучить некоторый SQL, но это будет определенно стоить того в конечном счете. Кроме того, вместо того, чтобы анализировать Ваши файлы журнала, возможно, Вы могли записать данные непосредственно в Вашу sqlite базу данных.

1
27.01.2020, 19:45
  • 1
    Спасибо за сценарий Python! Я думаю /usr/bin/sqlite3 работает тот же путь к сценариям оболочки (packages.debian.org/squeeze/sqlite3), хотя я никогда не использовал его. –  Teresa e Junior 27.01.2012, 10:04
  • 2
    Да, можно использовать /usr/bin/sqlite3 со сценариями оболочки однако я рекомендую избежать сценариев оболочки за исключением простых одноразовых программ и вместо этого использую язык как Python, который имеет лучшую обработку ошибок и легче поддержать и вырасти. –  aculich 27.01.2012, 18:46

Теги

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