Perl 如何使用计数器查找单词的位置?

Perl 如何使用计数器查找单词的位置?,perl,Perl,我目前正在编写一个代码,将某些单词更改为莎士比亚的单词。我必须提取包含单词的句子并将它们打印到另一个文件中。我必须删除。从每个文件的开头开始 首先,我将文件与文本按空格分开,所以现在我有了单词。接下来,我通过一个散列重复这些单词。散列键和值来自以制表符分隔的文件,该文件的结构如下:OldEng/ModernEng(lc\u Shakespeare\u lexicon.txt)。现在,我正试图找出每一个现代英语单词的确切位置,把它改成莎士比亚的;然后找出有变化的单词的句子,并将它们打印到不同的文件

我目前正在编写一个代码,将某些单词更改为莎士比亚的单词。我必须提取包含单词的句子并将它们打印到另一个文件中。我必须删除。从每个文件的开头开始

首先,我将文件与文本按空格分开,所以现在我有了单词。接下来,我通过一个散列重复这些单词。散列键和值来自以制表符分隔的文件,该文件的结构如下:OldEng/ModernEng(
lc\u Shakespeare\u 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);
#/usr/bin/perl-w
使用诊断;
严格使用;
#声明变量
我的$counter=();
我的%hash=();
我的$conv1=();
我的$conv2=();
我的$ssph=();
我的@text=();
我的$key=();
我的美元价值=();
我的$conversion=();
我的@rmv=();
我的$splits=();
我的$words=();
我的@word=();
我的$VAL=();
my$existingdir='/home/nelly/Desktop';
我的@file='classifications.txt';
我的$eng_words=();
我的$results=();
我的$storage=();
#打开文件到制表符分隔的单词

open(FILE),“自然语言处理很难做到正确,除非是在一些琐碎的情况下,例如,很难准确定义单词或句子的含义,而且当使用
U+0027
”撇号表示单引号和撇号时,很难区分它们“字符

没有任何示例数据,很难编写可靠的解决方案,但下面的程序应该相当接近

请注意以下几点

  • 使用警告
    优于shebang行上的
    -w

  • 一个程序应该包含尽可能少的注释,只要它是可理解的。太多的注释只会使程序更大,更难掌握,而不添加任何新的信息。标识符的选择应该使代码主要是自文档化的

  • 我认为
    use diagnostics
    是不必要的。大多数消息都是不言自明的,而且
    diagnostics
    会产生大量不必要的输出

  • 由于您要打开多个文件,因此使用autodie
更为简洁,这将避免显式测试每个
打开
调用是否成功

  • 最好使用词法文件句柄,如
    openmyfh…
    ,而不是全局句柄,如
    openfh…
    。首先,词法文件句柄在超出范围时会隐式关闭,这有助于通过使显式
    close
    调用变得不必要来整理程序

  • 我已经删除了程序顶部的所有变量声明,除了那些非空的。这种方法被认为是最佳实践,因为它有助于调试并帮助编写干净的代码

  • 在检查哈希中是否有匹配条目之前,程序使用
    lc
    对原始单词进行小写。如果找到翻译,则如果原始单词以大写字母开头,则使用
    ucfirst
    对新词进行大写

  • 我已经编写了一个正则表达式,它将从字符串
    $content
    的开头提取下一个句子。但是如果没有示例数据,这是我无法正确理解的事情之一,并且很可能存在问题,例如,以右引号或右括号结尾的句子

  • 使用严格;
    使用警告;
    使用自动模具;
    my$lexicon='lc_shakespeare_lexicon.txt';
    my$dir='/home/nelly/Desktop/input';
    my$existing_dir='/home/nelly/Desktop';
    我的$SECTURES='SECTURES.txt';
    我的%lexicon=do{
    打开我的($fh),“>”,“$existing_dir/$SECTURES”;
    打印“@words\n”;
    }
    }
    }
    
    你能发布一些输入数据吗?在需要之前声明变量,你就失去了
    my
    的一些好处。此外,所有这些赋值(除了
    my$existingdir='/home/nelly/Desktop';my@file='句子.txt';
    )都是无用的。很可能你将要使用
    索引
    pos
    和类似的东西-就像这样。我不知道你是否在这里正确设置了查找
    %hash
    。尝试使用或查看它是如何填写的。句子是如何存储在文件中的?每行一句话?有几个问题需要解决在Perl代码中,尝试在顶部添加
    使用警告;
    ,然后解析警告消息。最好让
    使用警告
    而不是
    -w
    。此外,
    数据
    是Perl的一个特殊文件句柄名称,因此您不应该对自己的文件使用它。当前的最佳做法是对文件句柄使用词法变量 (
    打开我的$in_fh,'谢谢你,这帮了大忙。我真的很感激你指出了我的弱点!!@Borodin我很难完全理解OP的意图。不过,听起来他们好像真的想重建句子结构。如果是这样的话,那么正则表达式解决方案似乎更合适,而不是按空格。
    s{(\w+)}{…}例如
    。顺便说一句,干得不错。
    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";
        }
      }
    }