使用 Powershell 返回每行文本文件的多个匹配项加上排序顺序

Returning Multiple Matches Per Line of Text File Plus Sort Order Using Powershell

我有一个测试脚本如下:

# listingParser.ps1     ---     by alphabetical order NOT numeric
   
$input_path = "C:\test\test3\Copy of 31832_226140__0001-00010.txt"
$output_file = "C:\test\test3\filterorder.txt"
$regexNum = '\d\d\d\s[A-Z][A-Z][A-Z]'           # Roll Entry Number and NAME

$result = select-string -Path $input_path -Pattern $regexNum -CaseSensitive | % { 
$_.Matches } | % { $_.Value } 

$result | Sort-Object > $output_file

输出如下所示:

001 BUZ
001 CAR
002 BUZ
003 BYE
005 BYE
007 CAR
008 BYF
009 BYF
010 CAR
011 BYG
012 CAR
014 CAR
017 BYT
018 BYT
021 CAD

问题是:

  1. 我的搜索 return 每行文本只有一个实例。文本文件的某些行包含搜索模式的多个示例,有些则没有。好吧,至少这是我对结果的解释(我刚刚再次检查以确定)如何在文件的任何行上指定 ALL 示例?

  2. 我的要求是对正则表达式的 [A-Z][A-Z][A-Z] 部分进行排序。考虑到原来搜索需要字符串的数字部分。

对于问题#2: 这个 PowerShell: How do I sort a text file by column? 描述了拆分每个字符串,在排序之前进行转换。我合并了这个但是出错了。最后我简化了它(删除了转换和排序方向)并让它工作了。

$result | Sort-Object { $_.split()[-1] } > $output_file

所以我想我已经解决了问题#2。

001 BUZ
002 BUZ
003 BYE
005 BYE
008 BYF
009 BYF
011 BYG
017 BYT
018 BYT
021 CAD
031 CAI
030 CAI
029 CAI
032 CAI
024 CAI

这样就剩下如何 return 我搜索的所有示例了。

如有任何建议,我们将不胜感激。

我相信使用 -AllMatches on Select-String should sort out the need to find all matches per line, another alternative could be to use [regex]::Matches(..) 可以找到匹配模式的所有外观。

关于需要按字母顺序对字符进行排序,我个人会使用:

{ [regex]::Match($_, '[A-Z]{3}').Value }

如果你需要在 之后按整数排序,你可以将它与:

结合使用
{ [int][regex]::Match($_, '\d{3}').Value }

您可以在下面看到两个示例的运行情况,首先我们可以为您的文件创建一个示例:

$dict = ([int][char]'A'..[int][char]'Z').ForEach([char])
function Ran {
    '{0:000}' -f (Get-Random -Maximum 100)
    $chars = 0..2 | ForEach-Object {
        Get-Random -Maximum $dict.Count
    }
    [string]::new($dict[$chars])
}

$testCase = 0..10 | ForEach-Object {
    [string]@(
        if($_ % 2) { Ran }
        Ran
    )
}

现在,$testCase 对我来说是这样的:

089 CDO
088 XRQ 060 AXS
023 XMH
019 OFM 021 PYD
054 PDY
041 GCG 003 HCJ
071 MCG
033 NAP 089 NPN
011 CEG
069 GDP 011 YTM
025 WQH

接下来我们可以同时测试Regex.MatchesSelect-String:

$sortChar = { [regex]::Match($_, '[A-Z]{3}').Value }
$sortInt  = { [int][regex]::Match($_, '\d{3}').Value }

$re = [regex]::Matches($testCase, '\d{3} [A-Z]{3}').Value |
Sort-Object $sortChar, $sortInt

$sls = ($testCase | Select-string -Pattern '\d{3} [A-Z]{3}' -CaseSensitive -AllMatches).Matches.Value |
Sort-Object $sortChar, $sortInt

最后我们可以比较两者是否给我们相同的 (sorted) 结果:

Compare-Object -ReferenceObject $re -DifferenceObject $sls -SyncWindow 0 -IncludeEqual

InputObject SideIndicator
----------- -------------
060 AXS     ==
089 CDO     ==
011 CEG     ==
041 GCG     ==
069 GDP     ==
003 HCJ     ==
071 MCG     ==
033 NAP     ==
089 NPN     ==
019 OFM     ==
054 PDY     ==
021 PYD     ==
025 WQH     ==
023 XMH     ==
088 XRQ     ==
011 YTM     ==

注意,如果使用 Regex.Matches 替代方案,在读取文件时您应该在 Get-Content 上使用 -Raw:

$content = Get-Content $input_path -Raw
[regex]::Matches($content, ...).Value | Sort-Object ... | Set-Content ...