-3

I have this expression in a switch statement for a script controlpanel

        $ctrlinpt=read-host ">>>"
        switch -regex ( $ctrlinpt )
        {
            <#1#>'^\w{2,}|\d{2,}$' { do this  }
            <#2#>'^c{1}|C{1}$' { do that }
            <#3#>'^l{1}|L{1}$' { do somethign else }
            <#4#>'^s{1}|S{1}$' { take a break }
            <#5#>'^exit$'{ go home }
        }

The first condition should match any input with more than one character and it does. However , if the input starts with one of the letters in the other conditions, it also matches their cases for example

"Task1" matches only case 1
"Legacy" matches case 1 and case 3
"supper" matches case 1 and case 4

I expect cases 2,3, and 4 to only match an input of exactly the one character stated. What am I doing wrong?

Laghorn
  • 43
  • 9
  • 1
    Change `'^l{1}|L{1}$'` to `'^l$'` (regex matching is case-insensitive in PowerShell by default) and so on – Mathias R. Jessen Sep 14 '22 at 09:55
  • game changer, thanks. I only added the quantifiers as an attempt to resolve this behavior. Any idea why it wont accept my solution (minus the quantifier)? – Laghorn Sep 14 '22 at 09:58
  • 1
    yeah the anchors`^`/`$` are interpreted as part of the subexpressions on either side of the alternation `|`, see answer below – Mathias R. Jessen Sep 14 '22 at 10:02

1 Answers1

1

The pattern '^l{1}|L{1}$' is interpreted as "a string starting with l OR a string ending with L" - and since PowerShell does case-insensitive comparisons by default, "a string starting with l" perfectly describes Legacy.

To fix this, you can nest the alternation in a grouping construct:

^(?:l{1}|L{1})$

... or use a character class:

^[lL]$

... or, since the matches are case-insensitive by default anyway, simply match on a single character literal:

^l$

Thus, your switch becomes:

$ctrlinpt = read-host ">>>"
switch -regex ( $ctrlinpt ) {
    '^(?:\w{2,}|\d{2,})$' { do this }
    '^c$' { do that }
    '^l$' { do somethign else }
    '^s$' { take a break }
    '^exit$' { go home }
}

Since regex isn't really required for the last 4 cases, I'd suggest removing the -regex mode switch altogether and use a predicate for the first case instead:

$ctrlinpt = read-host ">>>"
switch ( $ctrlinpt ) {
    { $_ -match '^(?:\w{2,}|\d{2,})$' } { do this }
    'c' { do that }
    'l' { do somethign else }
    's' { take a break }
    'exit' { go home }
}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206