PowerShell 正则表达式,对实例进行计数并将其用作同一正则表达式中的参考

PowerShell regex, count groups instances and use it as reference in the same regex

我正在尝试编写一个 powershell 正则表达式,其中有两组“日期”和“时间”,我需要这两个组同时出现。 这就是我现在所在的位置

(\d{8}-\d{8})((?<Dates>,\d{8}-\d{8})*)(\|)(\d\d:\d\d-\d\d:\d\d)(?<Hours>,\d\d:\d\d-\d\d:\d\d){0,}

需要匹配前四个但不需要匹配最后两个

20210701-20210718,20210801-20210814|18:00-07:00,12:00-13:00
20210701-20210718|18:00-07:00
20210701-20210718,20210801-20210814|18:00-07:00,12:00-13:00
20210701-20210718,20210801-20210814,20210801-20210814|18:00-07:00,12:00-13:00,12:00-13:00
20210701-20210718,20210801-20210814|18:00-07:00,12:00-13:00,12:00-13:00
20210701-20210718,20210801-20210814,20210801-20210814|18:00-07:00,12:00-13:00

我尝试将最后一个 {0,} 更改为 $Dates、$(Dates) 与 .Length 等的组合。 但可以在 google.

上找到任何内容

如果你有想法请告诉我。谢谢

Powershell 正则表达式由 .NET 驱动,因此您可以使用 平衡结构:

^(?<t>,?(?<Dates>\d{8}-\d{8}))+\|(?<-t>,?(?<Hours>\d\d:\d\d-\d\d:\d\d))+\r?$(?(t)(?!))

参见 .NET regex demo(注意 \r? 仅在使用 (?m) 标志时才需要)。

注意:如果字符串的开头和 | 之后不应该有逗号,您需要通过限制来调整 ,? 模式左侧上下文:

^(?<t>(?:(?<!^),)?(?<Dates>\d{8}-\d{8}))+\|(?<-t>(?:(?<!\|),)?(?<Hours>\d\d:\d\d-\d\d:\d\d))+\r?$(?(t)(?!))

请参阅 this .NET regex demo,其中 (?:(?<!^),)? 匹配一个可选逗号,前提是它没有出现在字符串的开头,而 (?:(?<!\|),)? 匹配一个可选逗号,如果它前面没有紧跟管道字符。

详情:

  • ^ - 字符串开头

  • (?: - 非捕获组匹配

    • (?<t>,?(?<Dates>\d{8}-\d{8}))+ - 一次或多次出现可选的 ,,然后是八位数字,-,八位数字被捕获到 Dates 组中(并且值为推到组“t”堆栈)
    • \| - 一个 | 字符
    • (?<-t>,?(?<Hours>\d\d:\d\d-\d\d:\d\d))+ - 一次或多次出现可选的 ,,然后是两位数字,:,两位数字,:,然后两位数字再次捕获到 Hours组(并从“t”组堆栈中弹出一个值)
  • \r?$(或 $,如果字符串是独立测试的)- line/string

    的结尾
  • (?(t)(?!)) - 条件:如果组“t”捕获堆栈不为空,匹配失败。

Powershell 测试:

我知道这是一个以正则表达式为中心的问题,但由于 PowerShell 已标记并且能够使用其他运算符进行分组和比较,您可以执行以下操作:

Get-Content file.txt | Foreach-Object {
    $row = $_
    $date,$time = $row -split '\|'
    if ($date.Split(',').Count -eq $time.Split(',').Count) {
        $row
    }
}

这假设您的行仅包含日期和时间。如果还有其他行,您将需要混合正则表达式以进行模式匹配。