Сравнение строк в файле с помощью Perl - PullRequest
0 голосов
/ 10 марта 2011

Я пытался сравнить строки между двумя файлами и совпадающими строками.

По какой-то причине приведенный ниже код проходит только через первую строку text1.txt и печатает оператор if независимо от того, совпадают две переменные или нет.

Спасибо

use strict;
open( <FILE1>, "<text1.txt" );
open( <FILE2>, "<text2.txt" );
foreach my $first_file (<FILE1>) {
    foreach my $second_file (<FILE2>) {
        if ( $second_file == $first_file ) {
            print "Got a match - $second_file + $first_file";
        }
    }
}
close(FILE1);
close(FILE2);

Ответы [ 7 ]

6 голосов
/ 10 марта 2011

Если вы сравниваете строки, используйте оператор eq. "==" сравнивает аргументы численно.

2 голосов
/ 10 марта 2011

Вот способ выполнить работу, если ваши файлы не слишком большие.

#!/usr/bin/perl
use Modern::Perl;
use File::Slurp qw(slurp);
use Array::Utils qw(:all);
use Data::Dumper;

# read entire files into arrays
my @file1 = slurp('file1');
my @file2 = slurp('file2');

# get the common lines from the 2 files
my @intersect = intersect(@file1, @file2);

say Dumper \@intersect;
2 голосов
/ 10 марта 2011

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

# This will find matching lines in two files,
# print the matching line and it's line number in each file.

use strict;

open (FILE1, "<text1.txt") or die "can't open file text1.txt\n";
my %file_1_hash;
my $line;
my $line_counter = 0;

#read the 1st file into a hash 
while ($line=<FILE1>){
  chomp ($line); #-only if you want to get rid of 'endl' sign
  $line_counter++;
  if (!($line =~ m/^\s*$/)){
    $file_1_hash{$line}=$line_counter;
  }
}
close (FILE1);

#read and compare the second file
open (FILE2,"<text2.txt") or die "can't open file text2.txt\n";
$line_counter = 0;
while ($line=<FILE2>){
  $line_counter++;
  chomp ($line);
  if (defined $file_1_hash{$line}){
    print "Got a match: \"$line\"
in line #$line_counter in text2.txt and line #$file_1_hash{$line} at text1.txt\n";
  }
}
close (FILE2);
1 голос
/ 09 января 2012

Если вы хотите количество строк,

my $count=`grep -f [FILE1PATH] -c [FILE2PATH]`;

Если вы хотите соответствующие строки,

my @lines=`grep -f [FILE1PATH]  [FILE2PATH]`;

Если вы хотите строки, которые не совпадают,

my @lines = `grep -f [FILE1PATH] -v [FILE2PATH]`;
1 голос
/ 10 марта 2011

Необходимо повторно открыть или сбросить указатель файла 2. Переместите команды open и close в цикл.

Более эффективный способ сделать это, в зависимости от файла и строкиразмеры будут состоять в том, чтобы проходить через файлы только один раз и сохранять каждую строку в файле 1 в хэше.Затем проверьте, была ли эта строка для каждой строки в файле 2.

0 голосов
/ 10 марта 2011

Взяв код, который вы разместили, и преобразовав его в реальный код Perl, я пришел к этому.лучше всего оставить до Text :: Diff .

use strict;
use warnings;

use Text::Diff;

print diff 'text1.txt', 'text2.txt';
0 голосов
/ 10 марта 2011

Это сценарий, который я написал, который пытается увидеть, идентичны ли два файла, хотя его можно легко изменить, поиграв с кодом и переключив его на eq. Как предположил Тим, использование хеша, вероятно, было бы более эффективным, хотя вы не могли гарантировать, что файлы сравнивались в том порядке, в котором они были вставлены, без использования модуля CPAN (и, как вы можете видеть, этот метод должен действительно использовать два цикла, но этого было достаточно для моих целей). Это не самый лучший сценарий за всю историю, но он может дать вам начало.

<code>
use warnings;</p>

<p>open (FILE, "orig.txt") or die "Unable to open first file.\n";
@data1 = ;
close(FILE);</p>

<p>open (FILE, "2.txt") or die "Unable to open second file.\n";
@data2 = ;
close(FILE);</p>

<p>for($i = 0; $i < @data1; $i++){
    $data1[$i] =~ s/\s+$//;
    $data2[$i] =~ s/\s+$//;
    if ($data1[$i] ne $data2[$i]){
        print "Failure to match at line ". ($i + 1) . "\n";
        print $data1[$i];
        print "Doesn't match:\n";
        print $data2[$i];
        print "\nProgram Aborted!\n";
        exit;
    }
}</p>

<p>print "\nThe files are identical. \n";</p>

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