2

私は Perl にかなり慣れていないため、次のパスワード入力コード スニペットの動作を把握するのに苦労しています。

use Win32::Console;

my $StdIn = new Win32::Console(STD_INPUT_HANDLE);
my $Password = "";

$StdIn->Mode(ENABLE_PROCESSED_INPUT());
local $| = 1;

print "Enter Password: ";
while (my $Data = $StdIn->InputChar(1)) {
    if ("\r" eq $Data ) {
        last;
    } 
    elsif ("\ch" eq $Data ) {
        if ( "" ne chop( $Password )) {
            print "\ch \ch";
        }
        next;
    }
    $Password .=$Data;
    print "*";
}

while (my $Data = $StdIn->InputChar(1)) {
    print "\nShow password? [y/n] ";
    if ("n" eq $Data) {
        last;
    }
    elsif ("y" eq $Data) {
        print "\nPassword: $Password\n";
        last;
    }
}

基本的に、スクリプトはユーザーにパスワードの入力を求め、*文字入力ごとに期待どおりに表示しますがEnter、入力を受け入れるには 2 回押す必要があります。print $passwordただし、2 番目の while ループを削除する (またはステートメントに置き換える) と、入力は を 1 回押すだけで済みEnterます。

yまた、2 番目の while ループで、ユーザーにorを入力するように求めるプロンプトが表示されることにも気付きましたn(押す必要はありませんEnter)。ユーザーが 'y' をShow password? [y/n]入力すると、パスワードを表示する前に行が繰り返されます。

この動作に関するいくつかの洞察をいただければ幸いです。

4

1 に答える 1

3

最初Enterは最初のwhileループから抜け出します。2 番目のwhileループは、プロンプトを表示する前に別の文字を待機します。別の文字を要求する前に、プロンプトを表示する必要があります (一度だけ表示します)。

物事をサブルーチンに分割すると、基本的なブロックを構築するのに役立ちます。

use strict; use warnings;
use Win32::Console;

run();

sub run {
    my $StdIn = Win32::Console->new(STD_INPUT_HANDLE);
    $StdIn->Mode(ENABLE_PROCESSED_INPUT);

    my $Password = prompt_password($StdIn, "Enter Password: ", '*');

    if ( prompt_echo($StdIn, "\nShow password? [y/n] ") ) {
        print "\nPassword = $Password\n"
    }

    return;
}

sub prompt_password {
    my ($handle, $prompt, $mask) = @_;
    my ($Password);

    local $| = 1;
    print $prompt;

    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        last if "\r" eq $Data;

        if ("\ch" eq $Data ) {
            if ( "" ne chop( $Password )) {
                print "\ch \ch";
            }
            next;
        }

        $Password .= $Data;
        print $mask;
    }

    return $Password;
}

sub prompt_echo {
    my ($handle, $prompt) = @_;

    local $| = 1;
    print $prompt;
    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        return if "n" eq $Data;
        return 1 if "y" eq $Data;
    }

    return;
}
于 2012-06-27T02:36:11.233 に答える