首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >perl中的模式匹配和正则表达式?

perl中的模式匹配和正则表达式?
EN

Stack Overflow用户
提问于 2017-02-03 07:18:22
回答 2查看 221关注 0票数 2

我正在处理perl和正则表达式中的chet程序,但是我没有得到想要的结果,因为我在散列中有所有的代词和动词,我是通过字符串循环的,如果它与散列键匹配,那么用当前的子字符串值替换散列键值。

程序输出

Eliza:嗨,我是心理治疗师。您的名字是什么?

亚当:,我叫亚当

Eliza:你好,亚当,你好吗?

adam:,我感觉很糟糕

Eliza:,你为什么感觉不好?

adam:,因为我病了

Eliza:,为什么你生病了?

不管“因为”字在最后一个问题,但输出应该是这样的

Eliza:,为什么你生病了?

关于我如何解决这个问题的任何建议。

代码:

代码语言:javascript
复制
sub makeQuestion{
    my ($patient) = @_;
    my %reflections = (
        "am"    =>   "are ",
        "was"   =>   "were ",
        "i"     =>   "you ",
        "i'd"   =>   "you would ",
        "i've"  =>   "you have ",
        "i'll"  =>   "you will ",
        "my"    =>   "your ",
        "are"   =>   "am ",
        "you've"=>   "I have ",
        "you'll"=>   "I will ",
        "your"  =>   "my ",
        "yours" =>   "mine ",
        "you"   =>   "me ",
        "me"    =>   "you "
    );

    my @toBes = keys %reflections;
    foreach my $toBe (@toBes) {
        if ($patient =~/$toBe\b/)
        {
            $patient=~ s/$toBe /$reflections{$toBe}/i;

        }

    }
    print "Why $patient? \n";
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-03 07:53:14

编辑:如@zdin所建议的,我将'\s'替换为' ',这将匹配任意数量的空白,同时也忽略了领先的空白空间。

这是因为您正在遍历%反射散列的全部键,并进行系统的替换。因此,您可以在循环1中找到"am“键,并将其替换为"are”。然后在循环8处找到"are“键,并将其替换为"am”。

当您使用单个单词替换时,您应该确保只使用split一次就运行了一个单词:

代码语言:javascript
复制
#!/usr/bin/perl

use strict;
use warnings;

my $question = '';

while ($question ne 'stop') {
    $question = <STDIN>;
    chomp $question;
    print makeQuestion($question)."\n";
}

sub makeQuestion{
    my ($patient) = @_;
    my @new_question;
    my %reflections = (
        "am"    =>   "are",
        "was"   =>   "were",
        "i"     =>   "you",
        "i'd"   =>   "you would",
        "i've"  =>   "you have",
        "i'll"  =>   "you will",
        "my"    =>   "your",
        "are"   =>   "am",
        "you've"=>   "I have",
        "you'll"=>   "I will",
        "your"  =>   "my",
        "yours" =>   "mine",
        "you"   =>   "me",
        "me"    =>   "you",
    );
    WORDS: foreach my $word (split ' ', $patient) {
        REPLACE: foreach my $key (keys %reflections) {
            if ($word =~ m{\A$key\Z}i) {
                $word =~ s{$key}{$reflections{$key}}i;
                 last REPLACE;
            }
        }
       push @new_question, $word;
    }
    return join ' ', @new_question;
}
票数 2
EN

Stack Overflow用户

发布于 2017-02-03 08:02:34

您的代码会进行循环替换,因为它总是处理整个短语。它取代了一个词,只是后来才替换了这个词。David Verdin的答复对此进行了解释,并展示了解决这一问题的方法。

这里有另一种方法

代码语言:javascript
复制
my $phrase =  join ' ', map { $reflections{$_} // $_ } split ' ', $patient;

拆分生成的单词列表被输入到地图地图将块中的代码应用于每个单词。在块内部,当前处理的元素位于默认的变量中。

如果单词是带有defined值的散列中的键,则返回该值,否则返回单词本身。这是由//运算符实现的。因此,所有具有散列键的单词都会被相应的值替换,而其他的则不会改变。他们的订单也被保留下来,因此我们可以根据需要处理我们的单词列表。

然后,将输出列表用空格连接起来,形成由'Why '加在前面的短语。

注意,split中的模式split与任意数量的空白相匹配。它通常用于将字符串“由空格”(改为“word”)中断,这是split的默认设置。

我想在发布的代码中添加一个关于正则表达式使用的注释。您不需要为匹配进行第一次测试就可以进行替换。你可以直接做

代码语言:javascript
复制
foreach my $item (@list) {
    $item =~ s/$pattern/$repl/;
}

如果$pattern$item中不匹配,则$item将保持不变。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42018775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档