2014-07-02 20 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

相关问题