Объединение двух файлов с регулярным выражением в Unix (в идеале с Perl) - PullRequest
1 голос
/ 08 июля 2011

У меня есть два следующих файла: connect.txt и answer.txt:

disconnect.txt

2011-07-08 00:59:06,363 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:459 - AnalyzedInfo had ActCode = Disconnected from: 40397400012 to:40397400032
2011-07-08 00:59:06,363 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:459 - AnalyzedInfo had ActCode = Disconnected from: 4035350012 to:40677400032

answered.txt

2011-07-08 00:59:40,706 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:404 - Normal Call Answered, billingid=2301986 from: 40397643433 to:403###34**
2011-07-08 00:59:40,706 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:404 - Normal Call Answered, billingid=2301986 from: 3455334459 to:1222
2011-07-08 00:59:48,893 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:404 - Normal Call Answered, billingid=2220158 from: 4035350012 to:40677400032

Я хотел бы создать объединение для этих файлов на основе полей from: и to: и вывод должен соответствовать полю из answer.txt. Например, в приведенных выше двух файлах вывод будет:

2011-07-08 00:59:48,893 [socketProcessor] DEBUG ProbeEventDetectorIS41Impl:404 - Normal Call Answered, billingid=2220158 from: 4035350012 to:40677400032

В настоящее время я делаю это, сравнивая каждую строку в файле 1 с каждой строкой в ​​файле 2, но хочу знать, существует ли эффективный способ (эти файлы будут в десятках гигабайт).

Спасибо

Ответы [ 3 ]

3 голосов
/ 08 июля 2011

Похоже, у вас есть сотни миллионов строк?

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

1 голос
/ 08 июля 2011

Сначала отсортируйте файлы по временным меткам from / to, если они еще не отсортированы таким образом.(Да, я знаю, что from / to хранится в виде секунд эпохи, но это все еще отметка времени.)

Затем возьмите отсортированные файлы и сравните первые строки каждого.

  • Если метки времени совпадают, у вас есть совпадение.Ура!Продвиньте строку в одном или обоих файлах (в зависимости от ваших правил для дублированных временных меток в каждом) и сравните снова.
  • Если нет, возьмите следующую строку в том файле, который имеет более раннюю временную отметку, и сравните снова.

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

Если ваши файлы не отсортированы надлежащим образом,тогда начальная операция сортировки может быть несколько дорогой для файлов в диапазоне размеров «десятки гигабайт каждый», но:

  1. Вы можете разбивать файлы на куски произвольного размера (в идеале достаточно малые для каждого чанкачтобы поместиться в память), отсортируйте каждый фрагмент независимо, а затем обобщите приведенный выше алгоритм из двух файлов до необходимого количества.
  2. Даже если вы этого не сделаете и столкнетесь с перегрузкой диска, связанной ссортировка файлов, размер которых превышает доступную память, сортировка, а затем выполнение одного прохода для каждого файла, все равно будет lot быстрее, чем любое решение, включающее декартово объединение.

Или вы можете просто использовать базу данных, как упоминалось в предыдущих ответах.Описанный выше метод будет более эффективным в большинстве, если не во всех случаях, но решение на основе базы данных будет легче написать, а также обеспечит большую гибкость для анализа ваших данных другими способами без необходимости полного сканирования черезкаждый файл каждый раз, когда вам нужно получить к нему доступ.

1 голос
/ 08 июля 2011

Если файлы большие, квадратичный алгоритм займет время жизни.

Вот скрипт Ruby, который использует только один поиск в хэш-таблице на строку в answer.txt:

def key s
  s.split('from:')[1].split('to:').map(&:strip).join('.')
end

h = {}
open 'disconnect.txt', 'r' do |f|
  while s = f.gets
    h[key(s)] = true
  end
end

open 'answered.txt', 'r' do |f|
  while a = f.gets
    puts a if h[key(a)]
  end
end

Как говорит ysth , все зависит от количества строк в файле disnect.txt. Если это действительно большое число 1 , то вы, вероятно, не сможете разместить все ключи в памяти, и вам понадобится база данных.


1. Количество строк в файле disnect.txt, умноженное (примерно) на 64, должно быть меньше, чем объем памяти на вашем компьютере.

...