2015-04-28 85 views
-1

這是我當前的腳本,嘗試將file_all.txt中的單詞與file2.txt中的單詞進行比較。它應該打印出file_all中不在file2中的任何單詞。Perl:比較兩個文件中的單詞

我需要將它們格式化爲每行一個字,但這不是更緊迫的問題。

我是新來的Perl ...我得到C和Python更多,但這是有點棘手,我知道我的變量分配關閉。

use strict; 
use warnings; 

my $file2 = "file_all.txt"; %I know my assignment here is wrong 
my $file1 = "file2.txt"; 

open my $file2, '<', 'file2' or die "Couldn't open file2: $!"; 
while (my $line = <$file2>) { 
    ++$file2{$line}; 
    } 

open my $file1, '<', 'file1' or die "Couldn't open file1: $!"; 
while (my $line = <$file1>) { 
    print $line unless $file2{$line}; 
    } 

編輯:哦,它應該忽略的情況...就像餡餅和PIE比較時一樣。並刪除撇號

這是我收到的錯誤:

"my" variable $file2 masks earlier declaration in same scope at absent.pl line 9. 
"my" variable $file1 masks earlier declaration in same scope at absent.pl line 14. 
Global symbol "%file2" requires explicit package name at absent.pl line 11. 
Global symbol "%file2" requires explicit package name at absent.pl line 16. 
Execution of absent.pl aborted due to compilation errors.
+1

看起來你是在正確的軌道上。問題是什麼? – mob

+0

如果我嘗試運行它,我會在absent.pl第6行獲得散列分配中奇數個元素。 absent.pl第7行散列分配中元素的奇數個數。 無法打開文件2:沒有這樣的文件或目錄在absent.pl第9行。 – user3295674

+0

我不確定這是什麼意思,因爲我是新來的Perl(對不起,如果這是一個愚蠢的問題!) – user3295674

回答

1

你的錯誤消息:

"my" variable $file2 masks earlier declaration in same scope at absent.pl line 9. 
"my" variable $file1 masks earlier declaration in same scope at absent.pl line 14. 
Global symbol "%file2" requires explicit package name at absent.pl line 11. 
Global symbol "%file2" requires explicit package name at absent.pl line 16. 
Execution of absent.pl aborted due to compilation errors.

你是$file2分配一個文件名,那麼後來您正在使用open my $file2 ...在第二種情況下使用我的$file2會掩蓋第一種情況下的使用。然後,在while循環的主體中,你假裝有一個散列表%file2,但你還沒有聲明它。

您應該使用更多的描述性變量名稱以避免概念混淆。

例如:

my @filenames = qw(file_all.txt file2.txt); 

使用變量與integer suffixes is a code smell

然後,將常規任務分解爲子例程。在這種情況下,您需要的是:1)獲取文件名並返回該文件中的單詞表的函數,以及2)獲取文件名和查找表並打印文件中的單詞的函數,但不會出現在查找表中。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Carp qw(croak); 

my @filenames = qw(file_all.txt file2.txt); 

print "$_\n" for @{ words_notseen(
    $filenames[0], 
    words_from_file($filenames[1]) 
)}; 

sub words_from_file { 
    my $filename = shift; 
    my %words; 

    open my $fh, '<', $filename 
     or croak "Cannot open '$filename': $!"; 

    while (my $line = <$fh>) { 
     $words{ lc $_ } = 1 for split ' ', $line; 
    } 

    close $fh 
     or croak "Failed to close '$filename': $!"; 

    return \%words; 
} 

sub words_notseen { 
    my $filename = shift; 
    my $lookup = shift; 

    my %words; 

    open my $fh, '<', $filename 
     or croak "Cannot open '$filename': $!"; 

    while (my $line = <$fh>) { 
     for my $word (split ' ', $line) { 
      unless (exists $lookup->{$word}) { 
       $words{ $word } = 1; 
      } 
     } 
    } 

    return [ keys %words ]; 
} 
+0

我將第一個更改爲$ file2,但仍然出現相同的錯誤。我究竟做錯了什麼? – user3295674

1

你幾乎沒有。

% sigil表示散列。你不能在一個散列中存儲一個文件名,你需要一個標量。

my $file2 = 'file_all.txt'; 
my $file1 = 'file2.txt'; 

您需要一個散列來計算出現次數。

my %count; 

要打開一個文件,指定它的名稱 - 它存儲在標量中,你還記得嗎?

open my $FH, '<', $file2 or die "Can't open $file2: $!"; 

然後,過程行的文件行:

while (my $line = <$FH>) { 
    chomp;    # Remove newline if present. 
    ++$count{lc $line}; # Store the lowercased string. 
} 

然後,打開第二個文件,並處理一行行,再次使用lc得到小寫的字符串。

要刪除apostophes,使用替代:

$line =~ s/'//g; # Replace ' by nothing globally (i.e. everywhere). 
+0

我試着在這裏解決一下,第二個也會是$ FH還是別的? http://www.codeshare.io/GFhX1(對不起,我覺得像一個兩歲的Perl) – user3295674

+0

@ user3295674:如果你不是從文件並行讀取,你可以使用相同的文件句柄。 – choroba

0

的問題是以下兩行:

my %file2 = "file_all.txt"; 
my %file1 = "file2.txt"; 

這裏你分配一個值,稱爲Perl中的SCALAR,到散列(由%印記表示)。哈希由由箭頭運算符(=>)分隔的鍵值對組成。例如

my %hash = (key => 'value'); 

哈希預計偶數的參數,因爲必須給他們既是關鍵。您目前只給每個Hash一個值,因此引發此錯誤。

的值賦給標,使用$印記:

my $file2 = "file_all.txt"; 
my $file1 = "file2.txt"; 
+0

我試過了,用我的$文件替換了最上面的兩行......但是我得到了「我的」變量$ file2在先前的聲明中在absent.pl第9行的同一範圍內聲明瞭掩碼。 「my」變量$ file1掩碼先前的聲明在相同範圍的absent.pl行14. 全局符號「%file2」需要在absent.pl行11處顯式包名。 全局符號「%file2」需要在absent.pl第16行顯式包名。 – user3295674

1

當你有提到你的問題:應該打印出任何的詞語file_all不在file2

這下面小編代碼做到這一點:

#!/usr/bin/perl 
use strict; 
use warnings; 

my ($file1, $file2) = qw(file_all.txt file2.txt); 

open my $fh1, '<', $file1 or die "Can't open $file1: $!"; 
open my $fh2, '<', $file2 or die "Can't open $file2: $!"; 

while (<$fh1>) 
{ 
    last if eof($fh2); 
    my $compline = <$fh2>; 
    chomp($_, $compline); 
    if ($_ ne $compline) 
    { 
     print "$_\n"; 
    } 
} 

file_all.txt:

ab 
cd 
ee 
ef 
gh 
df 

FILE2.TXT:

zz 
yy 
ee 
ef 
pp 
df 

輸出:

ab 
cd 
gh 
+0

這太棒了!我如何確保它不會與貓分開計算CAt? (案例無所謂) – user3295674

+0

之後,我想我會選擇你的答案,這是最簡潔的工作模式! – user3295674

+0

我想你可以從你自己的這個檢查。這將對待CAt和貓一樣。 – serenesat