【问题标题】:Regex works on regex101, but not in powershell... why?正则表达式适用于 regex101,但不适用于 powershell ......为什么?
【发布时间】:2022-08-18 23:16:08
【问题描述】:

我有这个测试数据:

^Test data



This is all just test data 


testing 123
ABC>space \"ABC\"

ABC>

我在 regex101.com 上设置了一个正则表达式 (^\\^|ERROR).*((|\\n|\\r|\\w|\\W)?)+(?=ABC>)

该表达式正在返回我在网站上想要的内容:

我正在使用我编写的这个 powershell 来获取与上述内容类似的内容并循环文件,并查找相同正则表达式的匹配项。

$files = gci \"\\\\server\\path\"
$content = @()


ForEach($file in $files){
    # Set script name
    $scriptname = \"ABC TEST_081722\"

    # Get the name of the task for the logfile\'s filename. 
    $taskname = \"THIS IS A TEST!!!\" 

    # Create log file with a datestamp MMDDYY
    $datestamp = (get-date).ToString(\'MMddyy\')
    $logfilepath = \"\\\\server\\path\\Logs\\$($taskname)\\$($file.basename).log\"
    $log_dir = \"\\\\server\\path\\Logs\\$($taskname)\\\"

    # Get the content of the log file. We are only interested in getting lines which match a regex for our command line and our output line. 
    $content_raw = get-content $logfilepath -raw

    $content_raw -match \"(^\\^|ERROR).*((|\\n|\\r|\\w|\\W)?)+(?=ABC>)\"
    
    Write-host -f yellow $file.fullname
    $matches
    $matches.clear()

                                                                        
    start-sleep -s 2
}

正则表达式在我的三个测试文件中的两个中找到匹配项,但不是第一个与我上面的示例具有完全相同的字符串内容的匹配项。为什么它在第二个和第三个文件中找到匹配但不是第一个?

第二个和第三个文件的内容是这样的

ABC>W !,MSG

ERROR^BATCH~Batch in use
ABC>space \"ABC\"

所以这两个文件没有以 \"^\" 符号开头的行。它以 \"ERROR\" 开头,我在正则表达式中使用 OR 语句说明了这一点。我只是不明白它如何能够找到以 \"ERROR\" find 开头的行,但没有从第一个以 \"^\" 克拉开头的文件中找到行。

    标签: regex powershell


    【解决方案1】:

    请尝试以下正则表达式:

    (?sm)(?:^\^|^ERROR).*?(?=\r?\nABC>)

    请注意,PowerShell 的运算符是 case-麻木不仁默认情况下(通常是 PowerShell)。为了区分大小写,请使用c-前缀运算符变体,即在这种情况下为-cmatch

    请参阅this regex101.com page,您可以在其中以交互方式试验文件中的文本。


    至于你尝试了什么

    • ^ 仅匹配开头单行如果MultiLine 正则表达式选项有效,您可以使用内联语法激活它(?m)- 注意,与 PowerShell 不同,regex101.com 已打开此选项默认(请参阅正则表达式输入字段右侧的选项字母,例如gm),这可以解释为什么您在那里没有看到问题。

      • 同样,(?s) 激活 SingleLine 正则表达式选项,这使得 . 也匹配换行符 (\n)。
    • ^\^|ERROR 仅将输入/行的开头^ 元字符应用于(转义的)^ 字符,而不应用于交替另一侧的ERROR (|)。

      • 您的测试数据不在输入文件的开头(如屏幕截图所示),导致^ 在没有(?m) 的情况下无效。
      • 相反,因为子字符串ERROR 是(意外地)不是锚定,它仍然匹配(但会匹配任何地方在一条线上)。

    笔记:

    • 在撰写本文时,regex101.com专用的 PowerShell 支持和最接近的 .NET (C#) 的默认值与 PowerShell 的默认值不一致.

    • 为了有关如何将 regex101.com 与 PowerShell 一起使用的指南,包括指向未来引入 PowerShell 支持的功能请求的链接,请参阅this answer

    【讨论】:

    • 这是一个很棒且内容丰富的答案,谢谢分享。只是好奇 regex101 站点是否不支持 powershell 正则表达式引擎,那么我们是否有任何其他在线演示站点或者它只是我们需要将其作为 .ps1 程序进行测试,只是想知道,谢谢。
    • 谢谢,@RavinderSingh13。 PowerShell 没有自己的正则表达式引擎,它使用 .NET,就像 C#(或任何 .NET 语言)一样。但是,(a) PowerShell 使用不同的默认值(?i),即暗示不区分大小写),(b) regex101.com 默认假定 (?m),这甚至不是 .NET 引擎的默认设置(全球的还假设匹配,是否适用取决于您使用的特定 .NET 方法/PowerShell 运算符),并且 (c) rege101.com 假设正则表达式被指定为C#逐字字符串,其转义规则与单引号 PowerShell 字符串不同。
    • 这是非常有用的@mklement0 感谢您的告知,干杯。
    • 很高兴听到它,@RavinderSingh13。总结一下:你能够已经使 regex101.com 与 PowerShell 一起使用,但是 (a) 您需要(首先选择风味 .NET (C#) 并)调整默认匹配选项,并且 (b) 如果您的 '...'-enclosed PowerShell 正则表达式包含 " 或 @987654349 @,您需要修改它以满足 C# 逐字字符串的语法。希望feature request to introduce specific PowerShell support,如果实施,将使这变得不必要。如果您也希望看到它实施,我建议对其进行投票。
    • 当然,我会尝试从移动设备上投票,很高兴知道事情已经开始实施 Powershell 的正则表达式在线演示(在 regex101 站点中),干杯。
    猜你喜欢
    • 1970-01-01
    • 2017-01-30
    相关资源
    最近更新 更多