【问题标题】:Search for words ending with 'ing' from a text file in perl从 perl 中的文本文件中搜索以 'ing' 结尾的单词
【发布时间】:2016-10-20 17:33:29
【问题描述】:

我有一个文本文件,我们称之为 file1.txt:

cats
and
dogs
are
running
around
|

john
loves
mary
|

I
am
swimming 
|

我正在尝试构建一个程序,该程序会查找以“ing”结尾的单词并将 CC 打印在同一文件或不同的 output.txt 文件中。

期望的输出

cats
and
dogs
are
running  CC
around
|

john
loves
mary
|

I
am
swimming CC
|

我浏览了论坛中的可用文章并尝试构建以下代码,但是它给了我一个任意结果,每个单词后跟“CC”。

use warnings;
use strict;

my $file = 'file1.txt';

open(my $word_fh,"file1.txt") or die "Couldn't open file file1.txt, $!";

my %word_match = map {chomp $_; $_ => 0} <$word_fh>;

close $word_fh;


open my $fh, '<', $file or die $!;

while (<$fh>){
    chomp;

    my @words_in_line = split;

    for my $word (@words_in_line){

        $word =~ /ing$/;
        $word .= '  CC' if exists $word_match{$word};

         print "    $word\n";
    }
    }

我得到的输出是这样的:

cats    CC
and CC
dogs    CC
are CC
running CC
around  CC
|   CC
john    CC
loves   CC
mary    CC
|   CC
I   CC
am  CC
swimming
|   CC

我知道我做错了什么。任何提示或建议将不胜感激。提前致谢!

【问题讨论】:

  • 直截了当:\w+ing\b - 用$0 CC 替换那些,你就完成了。 \w+ 确保字母在前面,\b 是单词边界。
  • 取消注释 use strictuse warnings。你会看到你错过了word_match第23行(你添加了一个's'),并且你使用了两次$w_fh而不是$word_fh..(虽然这不是你问题的解决方案,但你仍然应该这样做)
  • 您显示的代码不会产生您所说的输出。如果您希望我们帮助您,请出示您的真实代码,尤其是永远不要注释掉 use strictuse warnings

标签: regex perl pattern-matching


【解决方案1】:

我不清楚您的代码在做什么。例如,%word_match 哈希的意义是什么?还有为什么你把use strictuse warnings注释掉了?

这似乎是您对问题的过度思考,因为这对我来说似乎很简单。

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

while (<>) {
  chomp;
  $_ .= ' CCC' if /ing$/;
  print "$\n";
}

这是一个 Unix 风格的过滤器。它从 STDIN 读取并写入 STDOUT。所以,(假设它在一个名为 cccing 的文件中)你可以这样称呼它:

$ ./cccing < your_input.txt > your_output.txt

【讨论】:

  • 我们不知道该平台不是Windows。 perl cccing.pl ... 总是更安全
【解决方案2】:

那是因为您正在读取您的 file1.txt 两次并检查它们是否匹配。在while 循环中,如果file1.txt 的当前行也包含在file1.txt 的某处,则打印'CC'。由于它们是相同的文件,这始终是正确的,并且在每一行之后都会打印“CC”。

您可能受到this question 的启发,其中 OP 想要检查文件 A 中的单词是否也包含在文件 B 中。您的情况不同,因为您没有两个文件。

将第一次读取的 file1.txt 放入 %word_match 并仅遍历文件一次。您的行 $word =~ /ing$/; 仅检查 $word 是否以 ing 结尾,但将结果丢弃。这就像写作

$i > 5;
print "i is greater than 5\n";

您必须将其更改为

if ( $i > 5 ) {
    print "i is greater than 5\n";
}

总而言之,这给出了

#!/usr/bin/env perl

use strict;
use warnings;

open my $fh, '<', 'file1.txt' or die $!;
while ( <$fh> ){
    chomp;
    print $_;
    if ( /ing\s*$/ ) {
        print ' CC';
    }
    print "\n";
}
close($fh);

【讨论】:

  • 程序执行,但仅在“正在运行”一词旁边打印“CC”。 '猫和狗在 CC 周围跑来跑去,约翰爱玛丽,我在游泳' 它不会在游泳旁边打印 CC ..
  • swimming 包含一个尾随空格。它实际上是'swimming '。我更新了我的答案,但你可以自己想出来。
  • 我不确定我应该发布一个新问题还是自己在这里提问。是否可以在“if”部分包含多个条件,或者我应该使用“elsif”。例如,如果我还想在同一个文本文件中查找以“s”结尾的单词并在它们旁边打印“CC”,那么除了获取以“ing”结尾的单词之外,我应该使用“elsif”命令还是我可以在'if'下传递多个参数吗?另外,如果我想在同一个程序中查找以'd'结尾的单词并在它们旁边打印'DD','elsif'应该是最好的方法吗?提前致谢。
  • @Nandini143:你可以写if ( /ing\s*$/ or /s\s*$/ ) { ... }。或者您可以将其与if ( /(?:ing|s)\s*$/ ) { ... } 组合成一个正则表达式
【解决方案3】:

正如其他人评论的那样,您正在使用您的哈希%word_match 来测试文件中的每个单词是否存在于同一个文件中。当然,每个单词都是如此,所以你会得到一个 CC 附加到所有内容

去掉第一个open,构建散列的循环,以及对散列的测试,我认为这是最好的方法。它将像您自己的代码一样每行处理多个单词,并且还避免了在正则表达式模式中允许空格

Perl 代码

use strict;
use warnings;

my $file = 'file1.txt';

open my $fh, '<', $file or die $!;

while ( <$fh> ){
    chomp;

    my @words_in_line = split;

    for my $word ( @words_in_line ) {

        $word .= ' CC' if $word =~ /(?:ing|s)$/;
    }

    print "    @words_in_line\n";
}

输入

cats
and
dogs
are running around
|

john loves mary
|

I
am
swimming 
|

输出

cats CC
and
dogs CC
are running CC around
|

john loves CC mary
|

I
am
swimming CC
|

【讨论】:

    猜你喜欢
    • 2012-03-05
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多