2010-05-17 18 views
13

Bu soru, kodda yaptığım değişikliklerin, metin dosyasına gönderdiği değerleri etkilemediğinden emin olma ihtiyacından kaynaklanmaktadır. İdeal olarak, içeriğin aynı olup olmadığını, boşlukları ve hepsine bağlı olarak iki dosya adında ve return 1 veya return 0'da bir alt öğe alırdım. Metin işlemesinin Perl'in forté olduğu göz önüne alındığında, iki dosyayı karşılaştırıp aynı olup olmadıklarını (test edilmemiş kodun altında) belirlemek oldukça kolay olmalıdır. Ben (sans CPAN modülleri) düşünebilirizİki dosyanın içeriğinin aynı olup olmadığını belirlemek için Perl'i nasıl kullanabilirim?

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; 
} 

tek yolu, söz konusu iki dosya açın ve bir fark bulunana kadar çizgi-by-line bunları okumaktır. Fark bulunmazsa, dosyalar aynı olmalıdır. Ancak bu yaklaşım kısıtlı ve beceriksizdir. Toplam satır iki dosyada farklıysa ne olur? Çizgi sayısını belirlemek için açıp kapatmalı mıyım, sonra da metinleri taramak için tekrar açılmalı mıyım? Yuck.

Bu konuda perlfaq5 numaralı belgede hiçbir şey göremiyorum. Çekirdek Perl 5.6.1 dağılımıyla gelmedikçe modüllerden uzak kalmak istiyorum.

+0

Bu sorunun daha önce SO üzerinde gelmediğine şaşırdım. – Zaid

+1

neden diff kullanmıyorsunuz? - Eğer üzerindeyseniz * nix – heferav

+0

@heferav: Perl'e hitap ederek, hangi ustalıkla başa çıkabiliriz. Unix programlama konusunda pek fazla bir şey yapmadım, hepsi bu kadar;) – Zaid

cevap

28

core'da.

use File::Compare; 

if (compare("file1", "file2") == 0) { 
    print "They're equal\n"; 
} 
+0

Whew! Basit bir şey olacağını biliyordum. – Zaid

+0

'Dosya :: Karşılaştırma, sadece dosyaları açıp satır satırlarını okuyarak kabaca eşdeğerdir (ya da üçüncü bağımsız değişken kullanırsanız, blokla engelleme). Performans hakkında endişeleriniz varsa, aramadan önce dosya boyutunu ve inode numaralarını kontrol etmek isteyebilirsiniz. –

+0

Aslında File :: Compare dosya boyutunu kontrol eder. Kaynağa bakın http://cpan.uwinnipeg.ca/htdocs/perl/File/Compare.pm.html –

7

Dosyaların farklı olup olmadığını görmek için önce yapabileceğiniz birkaç (1) adet kontrol vardır. Dosyalar farklı boyutlara sahipse, açıkça farklıdırlar. stat işlevi, dosyaların boyutlarını döndürür. Ayrıca yararlı olacak başka bir veri parçasını da döndürecektir: inode numarası. İki dosya gerçekten aynı dosyaysa (aynı dosya adı her iki dosya için de girildiğinden veya her iki ad aynı dosya için sabit olduğundan), inode numarası aynı olacaktır. Bir dosya açıkça kendisi ile aynıdır. Bu iki kontrolün yasaklanması, iki yerel dosyayı birbirleriyle doğrudan karşılaştırmaktan başka bir eşdeğerlik açısından karşılaştırmanın daha iyi bir yolu değildir. Tabii ki, hatta satır satır yapmak için gerek yok, eğer arzu ederseniz büyük bloklarda okuyabilirsiniz.

#!/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"; 
+0

Soru, taşınabilir bir betik dili (Perl) bağlamındadır. Bu cevap OS ve dosya sistemi özeldir. İnodes'ların benzersiz ve karşılaştırılabilir olduğu varsayımı, Windows'ta (tüm dosya sistemleri) ve UNIX'teki blok tabanlı dosya sistemlerinde bile başarısız olacaktır, farklı birimler, bölümler, alt-öğeler vb. – Garen