Как я могу использовать Perl для определения идентичности содержимого двух файлов? - PullRequest
14 голосов
/ 17 мая 2010

Этот вопрос связан с необходимостью обеспечить, чтобы изменения, внесенные в код, не влияли на значения, выводимые в текстовый файл. В идеале я бы бросил саб, чтобы взять два имени файла и return 1 или return 0 в зависимости от того, идентично ли содержимое, пробелов и всего.

Учитывая, что обработка текста - удача Perl, должно быть довольно легко сравнить два файла и определить, идентичны они или нет (код ниже не проверен).

use strict;
use warnings;

sub files_match {

    my ( $fileA, $fileB ) = @_;
    open my $file1, '<', $fileA;
    open my $file2, '<', $fileB;

    while (my $lineA = <$file1>) {

        next if $lineA eq <$file2>;
        return 0 and last;
    }

    return 1;
}

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

Но этот подход ограничен и неуклюж. Что, если общее количество строк в двух файлах различается? Должен ли я открыть и закрыть, чтобы определить количество строк, а затем снова открыть для сканирования текстов? Тьфу.

Я не вижу ничего в perlfaq5 , относящегося к этому. Я хочу держаться подальше от модулей, если они не поставляются с основным дистрибутивом Perl 5.6.1.

Ответы [ 2 ]

31 голосов
/ 17 мая 2010

Это в ядре .

use File::Compare;

if (compare("file1", "file2") == 0) {
  print "They're equal\n";
}
7 голосов
/ 17 мая 2010

Есть пара проверок O (1), которые вы можете сначала выполнить, чтобы проверить, не отличаются ли файлы.

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

#!/usr/bin/perl

use strict;
use warnings;

use File::Compare ();

sub compare {
    my ($first, $second)             = @_;
    my ($first_inode, $first_size)   = (stat $first)[1, 7];
    my ($second_inode, $second_size) = (stat $second)[1, 7];

    #same file, so must be the same;
    return 0 if $first_inode == $second_inode;

    #different sizes, so must be different
    return 1 unless $first_size == $second_size;

    return File::Compare::compare @_;
}

print compare(@ARGV) ? "not the " : "", "same\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...