通过正则表达式过滤 powershell 中的字符串列表,然后按其中一个捕获组进行分组和排序

通过正则表达式过滤 powershell 中的字符串列表,然后按其中一个捕获组进行分组和排序

我正在寻找一种方法来通过正则表达式过滤 powershell 中的字符串列表,然后按其中一个捕获组进行分组和排序。

想象一下我的列表是这样的:

bogus0
ACBXYZ-0000 hello
bogus1
ACBXYZ-0000 hello again
bogus2
ACBXYZ-0001 world
bogus3
ACBXYZ-0001 world

首先我做了这个:

$list | select-string "^(ACBXYZ-\d+)(.*)"

输出

ACBXYZ-0000 hello
ACBXYZ-0000 hello again
ACBXYZ-0001 world
ACBXYZ-0001 world

然后我做了这个:

$list | select-string "^(ACBXYZ-\d+)(.*)" | % { "$($_.Matches[0].Groups[1].Value), $($_.Matches[0].Groups[2].Value.Trim(' ,-'))" } | sort | group | select name

输出

Name
----
ACBXYZ-0000, hello
ACBXYZ-0000, hello again
ACBXYZ-0001, world

但实际上我想输出这个:

Name
----
ACBXYZ-0000, hello
ACBXYZ-0001, world

因为数字后面的信息虽然很好,但并不是很重要。

有任何想法吗?

附言:我能够使用更复杂的脚本来实现这一点,但我正在寻找一行代码。

答案1

在回答和研究中关于 SO 的问题,我相信我有一个符合您初衷的解决方案。

毫无疑问,这可以进一步缩短(这编程高尔夫应该可以解决这个问题)但这对你发布的内容有用

 ? {$_ -match '^(ACBXYZ-\d+)'} | group {([Regex]::Match($_, [Regex]::new('^(ACBXYZ-\d+)'))).Value} | % {($_.group | sort le*)[0]}

在线试用

答案2

您需要一个哈希表来存储结果。哈希表是键值对的集合。在您的例子中,键将是“ACBXYZ-0000”字符串,值将是“hello”字符串。哈希表中的键是唯一的,这正是我们在这里所需要的。

例如:

$myHash = @{}
$myHash["ACBXYZ-0001"] = "hi there"  # set a value
Write-Output $myHash["ACBXYZ-0001"]  # retrieve the value

我已重写了您的脚本以在此处使用哈希表:

$list = gc text.txt
$out = @{}
$list | select-string "^(ACBXYZ-\d+)(.*)" | 
    % { $out[$_.Matches[0].Groups[1].Value] = $_.Matches[0].Groups[2].Value.Trim(' ,-') }
$out 

结果是:

Name                           Value                                                                                                           
----                           -----                                                                                                           
ACBXYZ-0000                    hello again                                                                                                     
ACBXYZ-0001                    world                                                                                                           

您可以看到第二个“ACBXYZ-0000”已覆盖第一个。如果您不喜欢这样,您可以在存储密钥之前使用 检查它是否已存在于哈希表中$out.ContainsKey()

我将把如何将结果输出为排序后的字符串列表的任务留给您。如果您遇到问题,请告诉我。

只是为了好玩,我还重写了你的脚本,使其更符合我的操作方式:

$list = gc text.txt
$out = @{}
$list | % {
    if ($_ -match "^(ACBXYZ-\d+)(.*)") 
    { 
        $out[$matches[1]] = $matches[2].Trim(' ,-') 
    } 
}
$out

相关内容