Быстрый способ открытия нескольких файлов после чтения входных файлов в perl

70
10

Формат входного файла (~ 5k строк) выглядит примерно так:

foo0: users/user1/temp1 users/user2/temp1 4.0
foo1: users/user2/temp1 users/user4/temp2 users/user4/temp1 1.0
foo2: users/user1/temp3 users/user2/temp3 2.0
foo4: users/user4/temp5 users/user2/temp6 users/user1/temp1 users/user3/temp1 4.0

Что мне нужно сделать, так это посмотреть на каждую строку, захватить каждый из путей, открыть файл и проверить что-то внутри на основе этого.

Например: для строки 1 скрипт должен открыть user1.txt и искать temp1 внутри user1.txt и что-то делать. Затем перейдите к user2.txt и найдите temp1 внутри и сделайте что-нибудь.

Для строки 2: Откройте users2.txt и найдите temp1; откройте users4.txt и найдите temp2; откройте users4.txt и найдите temp1.

Какой самый быстрый способ это сделать. В настоящее время я открываю и закрываю один за другим, и это, кажется, занимает много времени. Любая помощь оценили, спасибо!

спросил(а) 2012-08-22T00:30:00+04:00 8 лет, 1 месяц назад
1
Решение
-4

Я бы сделал что-то вроде этого:

#! /usr/bin/perl

use warnings;
use strict;

while ( <> ) {

## Remove last newline character.
chomp;

## Split line with spaces and save paths (all strings but the first and
## last one).
my @paths = split;
@paths = @paths[ 1 .. $#paths - 1 ];

## For each path...
for my $path ( @paths ) {

## Split with a slash, get second field and try to open it.
my @elements = split m|/|, $path;
open my $fh, q|<|, $elements[1] or die $!;

## Read line by line searching for the third field of the path, do
## something if found. You can add a 'last' instruction if you wish.
while ( my $line = <$fh> ) {
chomp;
if ( $line =~ m/\Q${elements[2]}\E/ ) {
## Do something;
}
}

close $fh or warn $!;
}
}

ответил(а) 2012-08-22T00:48:00+04:00 8 лет, 1 месяц назад
-6

Ну, в обычных системах скорость передачи данных на жестком диске является ограничением. Но есть способы, которые могут дать вам преимущество:

Многопоточность

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

Откройте n труб с функцией pipe где n - количество потоков. fork n раз из основной ("босса") нити. Каждая рабочая нить закрывает все несвязанные трубы Поток босса читает ваш входной файл и каждую команду направляет каждую команду в другой процесс. Таким образом, все рабочие процессы имеют равную рабочую нагрузку. Рабочие потоки выполняют поиск и т.д.

Если вы еще не сделали многопоточность с fork, это решение не будет работать для вас.

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

Придумайте лучший алгоритм

    Что и как вы ищете в каждом файле? Вы просто сопоставляете одно регулярное выражение с каждой строкой и затем выполняете некоторый код? Какой код? Является ли regexp чрезмерно сложным? Можете ли вы использовать некоторую эвристику, чтобы пропустить определенную часть файла? Вы пробовали Tie::File? Это позволяет избежать загрузки файла в память, который может помочь. Вы сравнили свой сценарий? Смотрите это руководство на perl.com для ознакомления. Какие части работают медленно? Можете ли вы уменьшить алгоритмическую сложность вашей программы? Т.е.: вы повторяете два раза по любому файлу? Это может быть неоптимальным.

ответил(а) 2012-08-22T00:58:00+04:00 8 лет, 1 месяц назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема