10

I capture two groups matched using the regexp code below:

[regex]$regex = "^([0-9]{1,20})(b|kb|mb|gb|tb)$"

$matches = $regex.match($minSize)

$size=[int64]$matches.Groups[1].Value
$unit=$matches.Groups[2].Value

My problem is I want to make it case-insensitive, and I do not want to use regex modifiers.

I know you can pass regex options in .NET, but I cannot figure out how to do the same with PowerShell.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mishkin
  • 5,932
  • 8
  • 45
  • 64
  • As a small side note, the pattern might be shortened using an optional character class instead of the alternation `^([0-9]{1,20})([kmgt]?b)$` – The fourth bird May 20 '20 at 21:49

5 Answers5

16

There are overloads of the static [Regex]::Match() method that allow to provide the desired [RegexOptions] programmatically:

# You can combine several options by doing a bitwise or:
$options = [Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [Text.RegularExpressions.RegexOptions]::CultureInvariant
# or by letting casting do the magic:
$options = [Text.RegularExpressions.RegexOptions]'IgnoreCase, CultureInvariant'

$match = [regex]::Match($input, $regex, $options)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
argonym
  • 853
  • 7
  • 13
  • 1
    Great answer! The accepted answer handles the OPs specific problem for case insensitivity, but this handles the general case to pass in any flags/options to the regex. – KyleMit May 20 '20 at 14:22
7

Use PowerShell's -match operator instead. By default it is case-insensitive:

$minSize -match '^([0-9]{1,20})(b|kb|mb|gb|tb)$'

For case-sensitive matches, use -cmatch.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
7

Try using -match instead. E.g.,

$minSize = "20Gb"
$regex = "^([0-9]{1,20})(b|kb|mb|gb|tb)$"
$minSize -match $regex #Automatic $Matches variable created
$size=[int64]$Matches[1]
$unit=$Matches[2]
aquinas
  • 23,318
  • 5
  • 58
  • 81
2

You can also include mode modifier like (?i) in your regex, like so (cmatch forces case sensitive match):

PS H:\> 'THISISSOMETHING' -cmatch 'something'
False
PS H:\> 'THISISSOMETHING' -cmatch '(?i)something'
True
Ro Yo Mi
  • 14,790
  • 5
  • 35
  • 43
jrobiii
  • 101
  • 3
2

After using [regex] type accelerator, Options property is ReadOnly and can't be changed. But you can call a constructor with RegexOptions parameter:

$regex = [System.Text.RegularExpressions.Regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$','IgnoreCase')

To pass multiple options use bitwise or operator on underlying values:

$regex = [regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$',[System.Text.RegularExpressions.RegexOptions]::Multiline.value__ -bor [System.Text.RegularExpressions.RegexOptions]::IgnoreCase.value__)

But simple addition seems to work, too:

[System.Text.RegularExpressions.RegexOptions]::Multiline + System.Text.RegularExpressions.RegexOptions]::IgnoreCase

It would even work when supplied numeric flag (35 = IgnoreCase=1 + MultiLine=2 + IgnorePatternWhitespace=32), altough relying on enum values directly is usually not a best practice:

$regex = [regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$',36)
$regex.Options
AdamL
  • 12,421
  • 5
  • 50
  • 74
  • 1
    Simple addition works as the options are bit flags and don't overlap. Also, the first example shows that Powershell allows a string for a function parameter that expects an enumeration (value). Powershell substitutes the value for the enumeration member which has a name that is a unique (possibly partial) match for the string value. But Powershell also allows multiple member values to be bitwise ORed by including all the (full not partial) names in a comma separated list (see argonym answer). 2nd example could be `$regex = [regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$','ignorecase,multiline')` – Uber Kluger Sep 24 '20 at 07:04