如何在perl中从终端获取输入

时间:2017-01-31 05:58:44

标签: perl

我正在创建一个简单的聊天机器人程序,如ELIZA

我正在从终端提问并发送回复对话框,但我的程序只接受第一个输入并重复。

例如,当我运行我的脚本时,输出可能是这样的:

[Eliza]: Hi, I'm a psychotherapist. What is your name?
user Input: hello my name is adam.
[Eliza]: hello adam, how are you?
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam

并且它无休止地重复。

我不知道我在哪里做错了。那么如何让我的程序从键盘读取下一行。

sub hello {
    print "[Eliza]: Hi, I'm a psychotherapist. What is your name? \n";
}


sub getPatientName {
    my ($reply) = @_;

    my @responses = ( "my name is", "i'm", "i am", "my name's" );

    foreach my $response ( @responses ) {

        if ( lc($reply) =~ /$response/ ) {
            return  "$'";
        }
    }

    return lc($reply);
}

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"
    );

    if ( $count == 0 ) {
        $patientName = getPatientName($patient);
        $count += 1;
        print "Hello $patientName , How are you? \n";
    }

    my @toBes = keys %reflections;

    foreach my $toBe (@toBes) {

        if ($patient =~/$toBe/) {
            $patient=~ s/$toBe/$reflections{$toBe}/i;
            print "$patient? \n";
        }
    }
}

sub eliza {

    hello();

    my $answer = <STDIN>;

    while ($answer) {
        chomp $answer;
        #remove . ! ;
        $answer =~ s/[.!,;]/ /;
        makeQuestion($answer);
    }
}

eliza();

2 个答案:

答案 0 :(得分:4)

您的while循环从不读取输入。 $answer在循环之前得到STDIN,并且可能有一个字符串,在while条件下评估为true。循环中的正则表达式无法改变这种情况。

因此,不仅没有为$answer分配新的输入,而且在第一次迭代之后,循环中根本没有任何变化。所以它会一直运行,根据相同的$answer打印问题。

你需要

while (my $answer = <STDIN>) {
    chomp $answer;
    # ...
}

代替。

每次评估while (...)的条件时,都会通过<STDIN>读取新输入,并将其分配给$answer。然后,每个新问题都使用新的$answer。注意如何在while条件内声明变量以在循环体内可用。这是一种很好的方法,可以将其范围限制在循环内部所需的位置。

文件句柄读取<...>undef(或出错时)返回EOF并且循环终止。见I/O Operators in perlop。终端的用户通常可以通过Ctrl-d实现此目的。

答案 1 :(得分:0)

使用命令行参数的典型Perl脚本 1)测试用户提供的命令行参数的数量 2)尝试使用它们。

见下文代码

#!/usr/bin/perl -w

# (1) quit unless we have the correct number of command-line args
$num_args = $#ARGV + 1;
if ($num_args != 2) {
    print "\nUsage: name.pl first_name last_name\n";
    exit;
}

# (2) we got two command line args, so assume they are the
# first name and last name
$first_name=$ARGV[0];
$last_name=$ARGV[1];

print "Hello, $first_name $last_name\n";