我知道之前已经问过这个问题,我知道在Perl中有一些功能可以让这个变得简单。但我想要的是对我的具体代码的建议。我想浏览我从文件中读取的每行文本,并将其与另一个文件中的同一行进行比较,如果它们不同则打印它们。
我已经尝试了尽可能多的这种变化,但我都没有尝试过。我发布的这个特定代码认为数组中的每个元素都与另一个元素中的元素不同。
use 5.18.2;
use strict;
use utf8;
printf "This program only compares two files.\n"
. "Here are the differences between "
. $ARGV[0] . " and " . $ARGV[1] . ":\n";
open FIRST_FH, '<', $ARGV[0];
chomp(my @file1 = <FIRST_FH>);
close FIRST_FH;
open SECOND_FH, '<', $ARGV[1];
chomp(my @file2 = <SECOND_FH>);
close SECOND_FH;
for(my $i=0; $i < scalar @file1; ++$i){
my $string = $file2[$i];
unless($_ =~ /$string/){
print "Difference found: @file1[$i], @file2[$i]\n";
}
}
答案 0 :(得分:1)
use utf8;
只是指示解释器将您的源文件读取为UTF-8。使用open
pragma将默认IO层设置为UTF-8(或手动指定'&lt;:encoding(UTF-8)'作为open
的第二个参数。)
当printf
足够时,不要使用print
(由于插值,通常会这样做)。在这个特定的例子中,我发现heredoc最具可读性。
将两个文件都读入内存效率很低。通过在while
循环中一次取一行来懒惰地迭代它们。
始终检查open
是否失败,并在错误消息中包含$!
。或者,use autodie;
,为您处理此问题。另外,使用词法文件句柄;当它们超出范围时它们会自动关闭,并且不会与其他裸字冲突(例如子程序和内置命令)。
请记住这些建议,新代码如下:
#!/usr/bin/perl
use 5.18.2; # Implicitly loads strict
use warnings;
use open qw(:encoding(utf8) :std);
print <<"EOT";
This program only compares 2 files.
Here are the differences between
$ARGV[0] and $ARGV[1]:
EOT
open(my $file1, '<', shift) or die $!;
open(my $file2, '<', shift) or die $!;
while (my $f1_line = <$file1>, my $f2_line = <$file2>)
{
if ($f1_line ne $f2_line)
{
print $f1_line, $f2_line;
}
}
但这仍然是一个天真的算法;如果一个文件删除了一行,所有后续行将在文件之间有所不同。为了正确地实现diff
之类的比较,您需要实现一种算法,以找到最长的公共子序列。考虑使用CPAN模块Algorithm::Diff
。
答案 1 :(得分:0)
为什么要使用$_
进行比较?你还没有定义哪个?
my $string = $file2[$i];
unless($_ =~ /$string/){
只需使用eq
或ne
if ( $file1[$i] ne $file2[$i] ) {
但是,我建议您对脚本进行大量的风格更改,从逐行处理开始,而不是在文件中进行诽谤。以下是我将如何完全重写它:
use 5.18.2;
use strict;
use warnings;
use autodie;
use utf8;
my ( $file1, $file2 ) = @ARGV;
open my $fh1, '<', $file1;
open my $fh2, '<', $file2;
while ( !eof($fh1) && !eof($fh2) ) {
chomp( my $line1 = <$fh1> );
chomp( my $line2 = <$fh2> );
if ( line1 ne $line2 ) {
warn "Difference found on line $.:\n $line1\n $line2\n";
}
}
warn "Still more data in $file1\n" if !eof $fh1;
warn "Still more data in $file2\n" if !eof $fh2;