2009-03-31 42 views

Trả lời

15

Bạn có thể chơi với thuật ngữ :: ReadKey. Đây là một ví dụ rất đơn giản, với một số phát hiện cho phím xóa lùi và xóa. Tôi đã thử nghiệm nó trên Mac OS X 10.5 nhưng theo ReadKey manual nó sẽ làm việc trong Windows. Các manual chỉ ra rằng trong Windows sử dụng đọc không chặn (ReadKey(-1)) sẽ thất bại. Đó là lý do tại sao tôi đang sử dụng ReadKey (0) về cơ bản là getc (nhiều hơn trên getc trong 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

Điều này không hoạt động trong Windows. Nó hoạt động tốt cho đến khi bạn đến để nhấn phím enter, khi bạn phải bấm nó bốn thời gian cho nó để phản ứng. Nếu bạn sử dụng ReadMode (2), sau đó nó hoạt động tốt, nhưng không echo cho đến khi bạn nhấn trở lại. Không hiển thị * có thể là một thay thế có thể chấp nhận được –

+2

Nó không hoạt động trên Windows vì giá trị ascii thập phân của phím Enter hoặc Return là 13 (CR: vận chuyển trở về). Một khi bạn thay thế dòng trong khi (ord ($ key = ReadKey (0))! = 10) với while (ord ($ key = ReadKey (0))! = 13), nó hoạt động tốt hơn :) – Damien

+0

Bạn có lẽ cũng sẽ muốn để kiểm tra "\ x03" (^ C); Ngoài ra, bạn có thể muốn phát ra "\ b \ b" chỉ khi độ dài ($ mật khẩu)> 0 hoặc dựa trên giá trị trả về của() để tránh xóa dấu nhắc nếu người dùng tiếp tục quay lại) – vladr

-5

Bạn đã thử lưu trữ chuỗi (để chương trình của bạn vẫn có thể đọc được) và tìm hiểu độ dài của nó rồi tạo chuỗi có cùng độ dài, nhưng chỉ sử dụng '*'?

+0

Thay thế ký tự bằng * khi nhập. –

7

Bạn nên xem Term::ReadKey hoặc Win32::Console. Bạn có thể sử dụng các mô-đun đó để đọc các nét chính và phát ra '*' hoặc bất kỳ từ nào.

25

Trước đây tôi đã sử dụng IO::Prompt cho việc này.

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): Mô-đun này không còn được duy trì nữa. Sử dụng mô-đun IO :: Prompter để thay thế. * – reinierpost

17

Nếu bạn không muốn sử dụng bất kỳ gói ... Chỉ dành cho UNIX

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

'chomp' sẽ tốt hơn' chop' –

1

xây dựng trên chương trình Pierr-Luc, chỉ cần bổ sung một số điều khiển trên backslashes. Với điều này, bạn không thể tiếp tục nhấn dấu gạch chéo ngược mãi mãi:

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

Không cần đếm $, độ dài ($ password) sẽ làm. – vladr

Các vấn đề liên quan