2

I'm writing a script that will accept user input via Read-Host (set to $String), and I want to avoid any issues that could be caused by having a blank value for the variables. Since I'll be using this a lot, I want to implement it into a function that verifies no invalid characters are being used.

I thought I could use an if statement with ![string]::IsNullOrEmpty($String) as one of the conditions:

Function Test-ValidCharacters ($String, $ValidCharacters) {  
  if (($String -match $ValidCharacters) -and (!([string]::IsNullOrEmpty($String)))) {
    return $true
  }
  else {return $false}
}

I also tried this:

Function Test-ValidCharacters ($String, $ValidCharacters) {  
  if (($String -match $ValidCharacters) -and ($String -ceq "")) {
    return $true
  }
  else {return $false}
}

In both of these cases, I can just hit enter when presented with the $String's Read-Host prompt and the script will behave as if the function returned $True (and then later encounter fatal errors). The other half works - if I include characters not specified by $ValidCharacters the function returns $False as expected.

I am sure I'm missing something here. I even tried doing a second nested if statement and got the same result.

Edit: Here's the code snippet where I call the function and notice the issue.

$ValidCharacters = '[^a-zA-Z0-9]'
$FirstN = Read-Host -Prompt "New user's first name"
While (Test-ValidCharacters $FirstN $ValidCharacters -eq $false) {
  Write-Output "$FirstN contains illegal characters. A-Z, a-z, and 0-9 are accepted."
  $FirstN = Read-Host -Prompt "New user's first name"
}
3
  • Try If(!([string]::IsNullOrWhitespace($String))){. Also, without knowing what $ValidCharacters is it is really hard to help. Commented Jun 15, 2021 at 23:50
  • 1
    You could use [validatescript({$_.Trim() -match '\w'})]$check = Read-Host 'User input here' and avoid the need of the function :) Commented Jun 15, 2021 at 23:58
  • It's a range regex - '[a-zA-Z0-9]' - sorry I didn't include it. Commented Jun 16, 2021 at 0:04

1 Answer 1

3

Assuming $ValidCharacters isn't itself an empty string and contains an anchored character-range regex (regular expression) that covers the entire input string, such as ^[a-z0-9./:]+$, given that the -match operator matches any substring by default (note that a better name for the parameter is therefore something like $ValidationRegex):[1]

  • In the first function definition, the RHS of your -and operation is redundant - it adds nothing to the conditional, because if $String -match $ValidCharacters is $true, then so is ! [string]::IsNullOrEmpty($String), by definition.

  • Conversely, in the second function definition your -and operation always returns $false, because $String -ceq "" is by definition $false, if the LHS returned $true.

Assuming that your intent is to prevent empty or all-whitespace input and to ensure that any string - trimmed of incidental leading and/or trailing whitespace - is composed only of expected characters, use the following:

Function Test-ValidCharacters ($String, $ValidCharacters) {
  # Note: no strict need for `return`.
  $String.Trim() -match $ValidCharacters
}

[1] Alternatively, stick with $ValidCharacters and pass a regex that describes only a single valid character, such as '[a-z0-9./:]', and construct the entire-string matching regex inside the function with '^' + $ValidCharacters + '+$'

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, the $ValidCharacters input is regex, '[a-zA-Z0-9]' in the test case. I tried your example to see if it behaved any differently, but I could still enter an empty response to Read-Host and it would evaluate as $true. I edited the original post to provide the use case of the function in case that's the cause of the issue.
@VictorArevalo You're always entering the while loop because: 1. your regex is wrong, instead of '[^a-zA-Z0-9]' it should be '^[a-z0-9]' Note, since match is case insensitive A-Za-z is not needed. thanks mklement0 for reminding of that :) 2. the condition on your while loop should encapsulate the function so PS will validate it first, on the other hand, asking if something is $false doesn't look very clean so for simplicity you can use While (-not (Test-ValidCharacters $FirstN $ValidCharacters)) { .... }
Thanks, @SantiagoSquarzon. My example regex should have been ^[a-z0-9./:]+$ (now fixed), given that -match matches any substring by default.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.