2014-07-02 19 views
1

我目前正在研究將某些單詞改爲莎士比亞單詞的代碼。我必須提取包含單詞的句子並將它們打印到另一個文件中。我必須從每個文件的開頭刪除.START。如何使用計數器查找單詞的位置?

首先我用空格分隔文本文件,所以現在我有文字。接下來,我通過散列迭代單詞。哈希鍵和值來自制表符分隔的文件,其結構如下OldEng/ModernEng(lc_Shakespeare_lexicon.txt)。現在,我試圖找出如何找到每個現代英語單詞的確切位置,將其改爲莎士比亞;然後用改變詞找到句子並將它們打印到不同的文件中。除了最後一部分外,大部分代碼都已完成。這是我到目前爲止的代碼:

#!/usr/bin/perl -w 
use diagnostics; 
use strict; 

#Declare variables 
my $counter=(); 
my %hash=(); 
my $conv1=(); 
my $conv2=(); 
my $ssph=(); 
my @text=(); 
my $key=(); 
my $value=(); 
my $conversion=(); 
my @rmv=(); 
my $splits=(); 
my $words=(); 
my @word=(); 
my $vals=(); 
my $existingdir='/home/nelly/Desktop'; 
my @file='Sentences.txt'; 
my $eng_words=(); 
my $results=(); 
my $storage=(); 

#Open file to tab delimited words 

open (FILE,"<", "lc_shakespeare_lexicon.txt") or die "could not open  lc_shakespeare_lexicon.txt\n"; 

#split words by tabs 

while (<FILE>){ 
    chomp($_); 
    ($value, $key)= (split(/\t/), $_); 
    $hash{$value}=$key; 
} 

#open directory to Shakespearean files 

my $dir="/home/nelly/Desktop/input"; 
opendir(DIR,$dir) or die "can't opendir Shakespeare_input.tar.gz"; 
#Use grep to get WSJ file and store into an array 

my @array= grep {/WSJ/} readdir(DIR); 

#store file in a scalar 
foreach my $file(@array){ 

    #open files inside of input 

    open (DATA,"<", "/home/nelly/Desktop/input/$file") or die "could not open $file\n"; 
    #loop through each file 

    while (<DATA>){ 
     @text=$_; 
     chomp(@text); 
    #Remove .START 
    @rmv=grep(!/.START/, @text); 

foreach $splits(@rmv){ 
    #split data into separate words 
    @word=(split(/ /, $splits)); 
    #Loop through each word and replace with Shakespearean word that exists 
    $counter=0; 

foreach $words(@word){ 
     if (exists $hash{$words}){ 
      $eng_words= $hash{$words}; 
      $results=$counter; 
      print "$counter\n"; 
      $counter++; 

#create a new directory and store senteces with Shakespearean words in new file called "Sentences.txt" 
mkdir $existingdir unless -d $existingdir; 
open my $FILE, ">>", "$existingdir/@file", or die "Can't open  $existingdir/conversion.txt'\n"; 
#print $FILE "@words\n"; 

close ($FILE); 

       }   
      } 
     } 
    } 
} 

close (FILE); 
close (DIR); 
+1

你可以發佈一些輸入數據嗎? – fugu

+2

通過在變量被需要之前聲明變量,你會失去'my'的一些好處。此外,所有這些作業(除了'my $ existingdir ='/ home/nelly/Desktop'; my @ file ='Sentences.txt';')都沒用。 – ikegami

+0

最有可能你會使用'索引''pos'等 - 就像這個[類似的SO問題(看看答案)](http://stackoverflow.com/a/4856558/2019415) 。我不知道你是否正確設置了查找'%hash'。嘗試使用['Data :: Dumper'](https://metacpan.org/pod/Data::Dumper)或['Data :: Printer'](https://metacpan.org/release/Data-Printer)看看它是如何填寫的。 –

回答

3

自然語言處理是很難得到正確的除了在平凡的情況下,例如,很難準確定義什麼是一個一句的意思,並且它是笨拙當它們都表示使用U+0027「撇號」字符'

沒有它很難寫出一個可靠的解決方案的任何實施例的數據,但下面的程序應該是合理的一個單引號和一個撇號以區分關閉

請注意以下

  • use warnings最好-w的家當線

  • 的程序應該包含儘可能少的意見儘可能長,因爲它是可以理解的。如果沒有增加任何新的信息,太多的評論只會讓程序變得越來越難掌握。標識符的選擇應該使代碼大多自我記錄

  • 我認爲use diagnostics是不必要的。大多數消息是相當不言自明,而diagnostics可產生大量不必要的輸出的

  • 因爲你打開多個文件,更簡潔到use autodie這將避免需要顯式測試每個open呼叫成功

  • 使用詞法文件句柄要好得多,如open my $fh ...而不是全局文件句柄,如open FH ...。一方面詞法文件句柄會當它超出範圍,這有助於通過使明確close調用不必要整理程序很多

  • 我已經刪除了所有的變量聲明從頂部被隱式關閉該程序除非是非空的程序。這種方法被認爲是最佳實踐,因爲它有助於調試和幫助編寫乾淨的代碼

  • 在檢查哈希中是否存在匹配的條目之前,程序使用lc來降低原始字。如果找到了翻譯,那麼如果原始單詞以大寫字母開頭,則新單詞將被大寫

  • 我寫了一個正則表達式,它將從字符串$content開始的下一個句子。但是,這是我不能沒有合適的樣本數據得到的,並且有可能會出現問題,比如事情之一,與同右引號或右括號結束句

use strict; 
use warnings; 
use autodie; 

my $lexicon  = 'lc_shakespeare_lexicon.txt'; 
my $dir   = '/home/nelly/Desktop/input'; 
my $existing_dir = '/home/nelly/Desktop'; 
my $sentences = 'Sentences.txt'; 

my %lexicon = do { 
    open my ($fh), '<', $lexicon; 
    local $/; 
    reverse(<$fh> =~ /[^\t\n\r]+/g); 
}; 

my @files = do { 
    opendir my ($dh), $dir; 
    grep /WSJ/, readdir $dh; 
}; 

for my $file (@files) { 

    my $contents = do { 
    open my $fh, '<', "$dir/$file"; 
    join '', grep { not /\A\.START/ } <$fh>; 
    }; 

    # Change any CR or LF to a space, and reduce multiple spaces to single spaces 
    $contents =~ tr/\r\n/ /; 
    $contents =~ s/ {2,}/ /g; 

    # Find and process each sentence 
    while ($contents =~/\s* (.+?[.?!]) (?= \s+ [A-Z] | \s* \z) /gx) { 
    my $sentence = $1; 
    my @words = split ' ', $sentence; 
    my $changed; 

    for my $word (@words) { 
     my $eng_word = $lexicon{lc $word}; 
     $eng_word = ucfirst $eng_word if $word =~ /\A[A-Z]/; 
     if ($eng_word) { 
     $word = $eng_word; 
     ++$changed; 
     } 
    } 

    if ($changed) { 
     mkdir $existing_dir unless -d $existing_dir; 
     open my $out_fh, '>>', "$existing_dir/$sentences"; 
     print "@words\n"; 
    } 
    } 
} 
+0

謝謝,這有助於ALOT。我真的很感激你如何指出我的弱點! – user3797544

+0

@Borodin我完全理解OP的意圖有點麻煩。然而,這聽起來像他們實際上想重建句子結構。如果是這樣的話,那麼正則表達式的解決方案似乎更合適,而不是空間分割。 '{(\ w +)} {...} eg'。在教育順便尼斯工作。 – Miller

相關問題