【问题标题】:Pass regex options to PowerShell [regex] type将正则表达式选项传递给 PowerShell [regex] 类型
【发布时间】:2012-10-19 15:16:44
【问题描述】:

我使用下面的正则表达式代码捕获了两个匹配的组:

[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

我的问题是我想让它不区分大小写,并且我不想使用正则表达式修饰符。

我知道您可以在 .NET 中传递正则表达式选项,但我不知道如何使用 PowerShell 来做同样的事情。

【问题讨论】:

  • 作为一个小旁注,可以使用可选字符类而不是替代 ^([0-9]{1,20})([kmgt]?b)$ 来缩短模式

标签: regex powershell case-insensitive


【解决方案1】:

使用[regex] 类型加速键后,Options 属性为只读且无法更改。但是您可以使用 RegexOptions 参数调用构造函数:

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

要传递多个选项,请对基础值使用按位或运算符:

$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__)

但简单的加法似乎也可以:

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

它甚至可以在提供数字标志 (35 = IgnoreCase=1 + MultiLine=2 + IgnorePatternWhitespace=32) 时工作​​,尽管直接依赖枚举值通常不是最佳做法:

$regex = [regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$',36)
$regex.Options

【讨论】:

  • 简单的加法作为选项是位标志并且不重叠。此外,第一个示例显示 Powershell 允许将字符串用于需要枚举(值)的函数参数。 Powershell 将值替换为具有唯一(可能是部分)匹配字符串值的名称的枚举成员。但是 Powershell 还允许通过在逗号分隔列表中包含所有(完整而非部分)名称来对多个成员值进行按位或运算(请参阅argonym 答案)。第二个例子可能是$regex = [regex]::new('^([0-9]{1,20})(b|kb|mb|gb|tb)$','ignorecase,multiline')
【解决方案2】:

改用 PowerShell 的 -match 运算符。默认情况下不区分大小写:

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

对于区分大小写的匹配,使用 -cmatch。

【讨论】:

  • 谢谢,但接受了阿奎那的回答,因为他为我提供了完整的例子
【解决方案3】:

静态[Regex]::Match() 方法的重载允许以编程方式提供所需的[RegexOptions]

# 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)

【讨论】:

  • 很好的答案!接受的答案处理了 OPs 不区分大小写的特定问题,但这处理了一般情况以将任何标志/选项传递给正则表达式。
【解决方案4】:

尝试使用 -match 代替。例如,

$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]

【讨论】:

    【解决方案5】:

    您还可以在您的正则表达式中包含mode modifier 之类的(?i),就像这样(cmatch 强制区分大小写匹配):

    PS H:\> 'THISISSOMETHING' -cmatch 'something'
    False
    PS H:\> 'THISISSOMETHING' -cmatch '(?i)something'
    True
    

    【讨论】:

    • 一般来说这可能是有效的,但 OP 说他不想那样做。
    猜你喜欢
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多