Perl-скрипт для чтения и печати строк из нескольких текстовых файлов? - PullRequest
3 голосов
/ 24 августа 2011

У нас есть 300+ текстовых файлов, которые в основном являются копиями электронных писем, каждый текстовый файл имеет следующий формат:

To: blabla@hotmail.com 
Subject: blabla 
From: bla1@hotmail.com 
Message: Hello World! 

Платформа, на которой я работаю в сценарии, - это Windows, и вселокальный (включая экземпляр Perl).Цель состоит в том, чтобы написать сценарий, который просматривает каждый файл (все находятся в одном каталоге) и распечатывает список каждого «уникального» адреса электронной почты в поле from.Концепция очень проста.

Кто-нибудь может указать мне правильное направление здесь?Я знаю, как запустить скрипт Perl, и я могу прочитать один файл и распечатать все детали:

 #!/usr/local/bin/perl
 open (MYFILE, 'emails/email_id_1.txt');
 while (<MYFILE>) {
    chomp;
    print "$_\n";
 }
 close (MYFILE);

Итак, теперь мне нужно прочитать и напечатать строку 3 этого файла, но выполните это действие не один раз, а для всех файлов.Я посмотрел в модуль File :: Find, это может быть полезным?

Ответы [ 5 ]

2 голосов
/ 25 августа 2011

Perl, одна строка, windows-версия:

perl -wE "@ARGV = glob '*.txt'; while (<>) { say $1 if /^From:\s*(.*)/ }"

Он проверит все строки, но напечатает, только если найдет действительный тег From:

2 голосов
/ 24 августа 2011

Какая платформа? Если Linux, то все просто:

foreach $f (@ARGS) {    
    # Do stuff 
}

, а затем позвоните с:

perl mything.pl *.txt

В Windows вам нужно сначала расширить подстановочный знак, поскольку cmd.exe не расширяет подстановочные знаки (в отличие от оболочек Linux):

@ARGV = map glob, @ARGV

foreach $f (@ARGS) {
    # Do stuff
}

извлечение третьей строки - это просто случай чтения каждой строки и подсчета, когда вы попали в строку 3, чтобы вы знали, как распечатать результаты.

2 голосов
/ 24 августа 2011

Встроенный glob() может предоставить вам список файлов в каталоге:

chdir $dir or die $!;
my @files = glob('*');

Вы можете использовать Tie::File для доступа к 3-й строке файла:

use Tie::File;

for (@files) {
    tie my @lines, 'Tie::File', $_ or die $!;
    print $lines[2], "\n";         
}
1 голос
/ 24 августа 2011

Вот мое решение (надеюсь, это не домашняя работа).

Он проверяет все файлы в текущем каталоге, имена которых заканчиваются на «.txt», без учета регистра (например, он найдет «foo»)..TXT ", что, вероятно, то, что вы хотите под Windows).Он также учитывает возможные вариации в ограничителях строки (по крайней мере, CR-LF и LF), ищет префикс From: без учета регистра и допускает произвольные пробелы после :.

#!/usr/bin/perl

use strict;
use warnings;

opendir my $DIR, '.' or die "opendir .: $!\n";
my @files = grep /\.txt$/i, readdir $DIR;
closedir $DIR;
# print "Got ", scalar @files, " files\n";

my %seen = ();
foreach my $file (@files) {
    open my $FILE, '<', $file or die "$file: $!\n";
    while (<$FILE>) {
        if (/^From:\s*(.*)\r?$/i) {
            $seen{$1} = 1;
        }
    }
    close $FILE;
}

foreach my $addr (sort keys %seen) {
    print "$addr\n";
}
1 голос
/ 24 августа 2011

Вы используете оболочку в стиле Unix? Вы можете сделать это в оболочке, даже не используя Perl.

grep "^ От:" ./* | сортировать | uniq -c "

Разбивка выглядит следующим образом:

  1. grep будет захватывать каждую строку, начинающуюся с «From:», и отправлять ее на ...
  2. sort, который отсортирует эти строки по альфа-каналам, а затем ...
  3. uniq, который отфильтрует двойные линии. Часть "-c" будет подсчитывать вхождения.

Ваш вывод будет выглядеть так:

    3 From: dave@example.com
    5 From: foo@bar.example.com
    etc...

Возможные проблемы: Я не уверен, насколько сложными будут ваши строки "От", например несколько адресов, разные форматы и т. д.

Вы можете улучшить этот шаг grep несколькими способами или заменить его сценарием Perl, который имеет менее широкие функциональные возможности, чем предлагаемый сценарий «все в одном».

Пожалуйста, прокомментируйте, если что-то не понятно.

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