2009-03-31 9 views

Antwort

15

Sie können mit Term :: ReadKey spielen. Hier ist ein sehr einfaches Beispiel mit einer Erkennung für Rücktaste und Löschtaste. Ich habe es auf Mac OS X 10.5 getestet, aber laut der ReadKey manual sollte es unter Windows funktionieren. Die manual zeigt an, dass unter Windows nicht blockierende Lesevorgänge (ReadKey(-1)) fehlschlagen. Deshalb benutze ich ReadKey (0), der im Grunde getc ist (mehr auf getc in libc manual).

#!/usr/bin/perl                                                 

use strict;                                                  
use warnings;                                                 
use Term::ReadKey;                                                

my $key = 0;                                                 
my $password = "";                                                

print "\nPlease input your password: ";                                           

# Start reading the keys                                              
ReadMode(4); #Disable the control keys                                           
while(ord($key = ReadKey(0)) != 10)                                            
# This will continue until the Enter key is pressed (decimal value of 10)                                  
{                                                    
    # For all value of ord($key) see http://www.asciitable.com/                                     
    if(ord($key) == 127 || ord($key) == 8) {                                         
     # DEL/Backspace was pressed                                            
     #1. Remove the last char from the password                                        
     chop($password);                                              
     #2 move the cursor back by one, print a blank character, move the cursor back by one                             
     print "\b \b";                                               
    } elsif(ord($key) < 32) {                                             
     # Do nothing with these control characters                                        
    } else {                                                 
     $password = $password.$key;                                            
     print "*(".ord($key).")";                                            
    }                                                   
}                                                    
ReadMode(0); #Reset the terminal once we are done                                        
print "\n\nYour super secret password is: $password\n"; 
+3

Dies funktioniert nicht unter Windows. Es funktioniert gut, bis Sie die Enter-Taste drücken, wenn Sie es vier Mal drücken müssen, damit es reagiert. Wenn Sie ReadMode (2) verwenden, funktioniert es gut, aber es gibt kein Echo, bis Sie auf Return drücken. Das Anzeigen des * kann keine akzeptable Alternative sein. –

+2

Es funktioniert nicht unter Windows, weil der Dezimal-ASCII-Wert der Enter- oder Return-Taste 13 ist (CR: Wagenrücklauf). Sobald du die Zeile while (ord ($ key = ReadKey (0))! = 10) mit while (ord ($ key = ReadKey (0))! = 13) ersetzt hast, funktioniert es besser :) – Damien

+0

wirst du wahrscheinlich auch wollen nach "\ x03" (^ C) suchen; Außerdem möchten Sie wahrscheinlich "\ b \ b" nur ausgeben, wenn die Länge ($ password)> 0 oder der Rückgabewert von chop() ist (um zu verhindern, dass die Eingabeaufforderung gelöscht wird) – vladr

-5

Haben Sie versucht, die Zeichenfolge zu speichern (so dass Ihr Programm es immer noch lesen kann) und seine Länge zu ermitteln, dann erstellen Sie eine Zeichenfolge der gleichen Länge, aber verwenden Sie nur '*'?

+0

Ersetzen Sie das Zeichen mit *, wie sie es eingeben. –

7

Sie sollten sich entweder Term::ReadKey oder Win32::Console ansehen. Sie können diese Module verwenden, um die einzelnen Tastenanschläge zu lesen und '*' oder was auch immer auszugeben.

25

In der Vergangenheit habe ich IO::Prompt zum Einsatz.

use IO::Prompt; 
my $password = prompt('Password:', -e => '*'); 
print "$password\n"; 
+3

* [STATUS ] (http://search.cpan.org/dist/IO-Prompt/lib/IO/Prompt.pm#STATUS): Dieses Modul wird nicht mehr gepflegt. Verwenden Sie stattdessen das IO :: Prompter Modul. * – reinierpost

17

Wenn Sie keine Pakete verwenden möchten ... Nur für UNIX

system('stty','-echo'); 
chop($password=<STDIN>); 
system('stty','echo'); 
+0

'chomp' wäre besser als' chop' –

1

Aufbauend auf Pierr-Luc Programm, haben soeben eine gewisse Kontrolle über die Schrägstriche. Damit können Sie nicht für immer Backslash drücken:

sub passwordDisplay() { 
    my $password = ""; 
    # Start reading the keys 
    ReadMode(4); #Disable the control keys 
    my $count = 0; 
    while(ord($key = ReadKey(0)) != 10) { 
      # This will continue until the Enter key is pressed (decimal value of 10) 
      # For all value of ord($key) see http://www.asciitable.com/ 
      if(ord($key) == 127 || ord($key) == 8) { 
        # DEL/Backspace was pressed 
        if ($count > 0) { 
          $count--; 
          #1. Remove the last char from the password 
          chop($password); 
          #2 move the cursor back by one, print a blank character, move the cursor back by one 
          print "\b \b"; 
        } 
      } 
      elsif(ord($key) >= 32) { 
        $count++; 
        $password = $password.$key; 
        print "*"; 
      } 
    } 
    ReadMode(0); #Reset the terminal once we are done 
    return $password; 
} 
+0

Keine Notwendigkeit für $ count, Länge ($ Passwort) wird ausreichen. – vladr