我正在寻找一种方法来通过正则表达式过滤 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
答案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