【问题标题】:Stopword removal and save the new file去除停用词并保存新文件
【发布时间】:2011-07-08 05:17:57
【问题描述】:

我有需要从中删除停用词的文本文件。我将停用词存储在文本文件中。我将“停用词”文本文件加载到我的 Perl 脚本中,并将停用词存储在一个名为“stops”的数组中。

目前我正在加载一组不同的文本文件,并将它们存储在一个单独的数组中,然后进行模式匹配以查看是否有任何单词确实是停用词。 我可以打印停用词并知道文件中出现了哪些停用词,但是如何将它们从文本文件中删除并存储一个新的文本文件以使其没有停用词?

即停用词: 这 一种 到 的 和 进入

文本文件: “女孩开车撞到男人”

结果文件: 女孩开着撞车的男人

我将文件加载到:

$dirtoget = "/Users/j/temp/";
opendir( IMD, $dirtoget ) || die("Cannot open directory");`
@thefiles = readdir(IMD);`

foreach $f (@thefiles) {
if ( $f =~ m/\.txt$/ ) {

    open( FILE, "/Users/j/temp/$f" ) or die "Cannot open FILE";

    while (<FILE>) {
        @file = <FILE>;

这是模式匹配循环:

  foreach $word(split) {
                foreach $x (@stop) {
                   if  ($x =~ m/\b\Q$word\E\b/) {
                 $word='';
                        print $word,"\n";

$word 设置为空。

或者我可以这样做:

    $word = '' if exists $stops{$word};

我只是不确定如何将输出文件设置为不再包含匹配的单词。 将不匹配的单词存储在数组中并将它们输出到文件中是愚蠢的吗?

【问题讨论】:

    标签: regex arrays perl split pattern-matching


    【解决方案1】:

    就地覆盖文件是可能的,但很麻烦。 Unix 这样做的方法是将非停用词输出到标准输出(默认情况下 print 会这样做),然后将其重定向

    ./remove_stopwords.pl textfile.txt > withoutstopwords.txt
    

    然后继续处理文件withoutstopwords.txt。这也允许在管道中使用程序。

    【讨论】:

    • 这将打印所有必须删除的单词,但是如何从原始文件中删除它们?
    • mv withoutstopwords.txt textfile.txt。或者将它们保存在一个数组中,然后将它们写出来。
    【解决方案2】:

    更短:

    use strict;
    use warnings;
    use English qw<$LIST_SEPARATOR $NR>;
    
    my $stop_regex 
        = do { 
            local $LIST_SEPARATOR = '\\E|\\Q';
            eval "qr/\\b(\\Q@{stop}\\E)\\b/";
        };
    @ARGV = glob( '/Users/j/temp/*.txt' );
    while ( <> ) { 
        next unless m/$stop_regex/;
        print "Stop word '$1' found at $ARGV line $NR\n";
    }
    

    你想用这些词做什么?如果你想替换它们,那么你可以这样做:

    use English qw<$INPLACE_EDIT $LIST_SEPARATOR $NR>;
    local $INPLACE_EDIT = 'bak';
    
    ...
    while ( <> ) { 
        if ( m/$stop_regex/ )
            s/$stop_regex/$something_else/g;
        }
        print;
    }
    

    $INPLACE_EDIT 处于活动状态时,perl 会将打印转储到一个“.bak”文件中,当它移动到下一个文件时,它会将.bak 写入原始文件。 如果这就是你想要做的。

    【讨论】:

      【解决方案3】:

      您可以使用substitution operator 从文件中删除单词:

      use warnings;
      use strict;
      
      my @stop = qw(foo bar);
      while (<DATA>) {
          my $line = $_;
          $line =~ s/\b$_\b//g for @stop;
          print $line;
      }
      
      __DATA__
      here i am
      with a foo
      and a bar too
      lots of foo foo food
      

      打印:

      here i am
      with a
      and a  too
      lots of   food
      

      【讨论】:

      • 如果我编辑您的代码以接收我的文件:use warnings; open( STOPWORD, "/Users/j/stopWordList.txt" ) or die "Can't Open: $!\n"; @stops = &lt;STOPWORD&gt;; $dirtoget = "/Users/j/temp/"; opendir( IMD, $dirtoget ) || die("Cannot open directory"); @thefiles = readdir(IMD); foreach $f (@thefiles) { if ( $f =~ m/\.txt$/ ) { open( FILE, "/Users/j/temp/$f" ) or die "Cannot open FILE"; while (&lt;FILE&gt;) { my $line = $_; $line =~ s/\b$_\b//g for @stops; print $line; } } } 这似乎只是打印整个文件?
      • 它应该打印输入文件的所有行,并删除停用词,就像我的示例所示。
      • @jenniem001 - 试试chomp(@stops=&lt;STOPWORDS&gt;)。如果不调用chomp,所有停用词的末尾都会有换行符。
      猜你喜欢
      • 2011-07-07
      • 1970-01-01
      • 2020-06-24
      • 2020-08-10
      • 2014-05-20
      • 2019-01-25
      • 2015-09-05
      • 2017-01-21
      • 2018-11-21
      相关资源
      最近更新 更多