PowerShell: how to check how many digits were entered for user pin

Viewed 190

I'm trying to write a powershell script that asks for a user to input a 4 digit pin, and if the number is not equal to 4, a warning is issued.

Here's what I have but it doesn't seem to work...

[int]$userPin = read-host 'type in your user pin'
if ($userPin.length -ne 4) {
  write-host "Error, Pin must be 4 numbers"
}

this code writes the error message no matter what... Any help is appreciated! THANKS!

2 Answers
$userPin = while ($true) {
  $entered = Read-Host 'type in your user pin'
  if ($entered.Trim() -match '^\d{4}$') { [int] $entered; break }
  Write-Warning "$entered is not a 4-digit number; please try again."
}

The above keeps prompting until a 4-digit number is entered, and stores it as an [int] instance in variable $userPin.

Note that regex matching is used first to ensure that exactly 4 decimal digits (\d{4})[1] were entered, using -match, the regular-expression matching operator. That way, entering non-digits is ruled out up front, without causing the error you'd get if you cast a value with non-digits directly to [int].


As for what you tried:

By type-constraining your $userPin variable to type [int] ([int] $userPin = ...), you force its value - both the initial value and any value assigned later - to that type, and an instance of [int] (System.Int32) has no .Length property (whereas the original [string] instance returned from Read-Host does).

By default, PowerShell ignores attempts to access non-existent properties and returns $null, so your $userPin.length -ne 4 conditional is equivalent to $null -ne 4, which is always true.


[1] Strictly speaking, \d matches not just the ASCII-range decimal digits 0 through 9, but other Unicode characters classified as digits too. To disambiguate, you could use [0-9] instead, though that is probably very rarely needed in pratice.

My take on mklement0's excellent answer, same concept, keep asking until user's input is 4 digits.

$inputBlock = {
    try
    {
        [validatescript({[regex]::Match($_,'^\d{4}$').Length -eq 4})]
        $UserInput = Read-Host 'Type in your user PIN'
        
        $UserInput
    }
    catch
    {
        Write-Warning "Error, PIN must be 4 numbers"
        & $inputBlock
    }
}

$userInput = & $inputBlock
Related