在 PowerShell 中进一步指定 Select -unique

Further Specifying Select -unique in PowerShell

我正在使用 PowerShell 重新格式化大型数据库。原始数据由设备标签名称和数据点组成。原始文件重复每个数据点的标签。此外,还有许多具有相同数据点的相似(不相同)标签。这是原始示例:

40028 "ALBENI F1" "1 "     0.00   -14.00    12.10
40028 "ALBENI F1" "1 "     2.70   -13.90    11.80
40028 "ALBENI F1" "1 "     4.50   -13.80    11.60
40028 "ALBENI F1" "1 "     7.30   -13.60    11.10
40028 "ALBENI F1" "1 "    10.00   -12.70    10.40
40028 "ALBENI F1" "1 "    12.30   -11.80     9.70
40028 "ALBENI F1" "1 "    12.70   -11.30     9.50
40028 "ALBENI F1" "1 "    14.50    -9.40     8.70
40028 "ALBENI F1" "1 "    16.30    -7.40     7.80
40028 "ALBENI F1" "1 "    16.80    -6.80     6.90
40028 "ALBENI F1" "1 "    17.20    -5.50     5.30
40028 "ALBENI F1" "1 "    17.80    -3.50     3.50
40028 "ALBENI F1" "1 "    18.20     0.00     0.00
40030 "ALBENI F2" "2 "     0.00   -14.00    12.10

在 Powershell 中,我设法让它看起来像这样:

40028 "ALBENI F1 " "1 " "YES"
 , 0.00, -14.00, 12.10,
 , 2.70, -13.90, 11.80,
 , 4.50, -13.80, 11.60,
 , 7.30, -13.60, 11.10,
 , 10.00, -12.70, 10.40,
 , 12.30, -11.80, 9.70,
 , 12.70, -11.30, 9.50,
 , 14.50, -9.40, 8.70,
 , 16.30, -7.40, 7.80,
 , 16.80, -6.80, 6.90,
 , 17.20, -5.50, 5.30,
 , 17.80, -3.50, 3.50,
 , 18.20, 0.00, 0.00,
  40063 "CGS " "1 " "YES"
 , 0.00, -620.00, 680.00,

这就是我想要的格式。如您所见,我将所有标签都变成了单个 headers,并去掉了 ALBENI F2,因为它是 F1 的重复。我的问题是,为了到达那里,我使用了 select-object -unique。根据需要,这消除了所有重复的 headers 和重复数据集。然而,它也删除了其他完全不同的标签上的重复数据点。这是无法接受的;因此,我需要一种方法来摆脱重复的标签和数据集,同时将所有数据点保留在唯一标签上,即使这些数据点与其他标签中的数据点相同。

如果有帮助,这是我的代码:

Get-Content (inputfile)|select -skip 2| select-string '}' -NotMatch |
    %{$_ -replace '"\s+(\-?\d+\.\d+)\s+(\-?\d+\.\d+)\s+(\-?\d+\.\d+)','"" ,, , , ,'}| 
    %{$_ -split '"\s+,'} |
    select -unique |
    %{$_ -replace '"\s+("\w+")', ' "  "YES"'}| 
    %{$_ -replace '"\s+("\w+\s+")', ' "  "YES"'} |(outputfile)

里面有很多东西,而且一切正常。我只需要另一种整理重复项的方法。想法?

我将在这里采用不同的方法,将您的数据转换为 objects,然后您可以更轻松地过滤:

$data = Get-Content $inputfile -Raw # PowerShell 3+
#$data = (Get-Content $inputfile) -join '\n' # Use this with PowerShell 2
$obj = $data -replace ' {2,}', ' ' | ConvertFrom-Csv -Delimiter ' '

现在你有一个 collection 的 objects 属性,你可以根据需要进行过滤,例如:

$obj | Where-Object { $_.40028 -eq 40028 }

为了更好的可读性,您可能希望通过管道传输到 Format-Table 以查看其实际工作原理。

从你的问题中有点不清楚你最终想从中得到什么,所以很难证明更具体的查询。如果您对每一列都有 headers,这也会有所帮助,因为它会产生更有意义的 属性 名称。

说明

$data -replace ' {2,}', ' ' | ConvertFrom-Csv -Delimeter ' '

这会将 2 个或更多 space 的所有实例折叠成一个 space,这将有助于转换为 CSV。

我们告诉 ConvertFrom-Csv 我们正在使用单个 space 作为分隔符,然后它就发挥了它的魔力。它理解引用的字段,所以这在这里很有效。

如果您有 headers,您可以使用 -Header 指定它们,以便生成的属性具有良好的名称。

好的,所以我采取了完全不同的方法;我首先将文件拆分为 headers 和数据。然后,我用 get-unique 过滤了 headers,只留下数据。然后我将数据分成几组并在每个位置插入适当的 headers。这摆脱了所有额外的 headers,并将整个文件放入我需要的格式。我的全部代码如下。

[cmdletbinding()]
Param(
[Parameter(mandatory=$true,position=1)]
[string]$InputFilePath,
[Parameter(mandatory=$true,position=2)]
[string]$OutputFilePath
)

Get-Content $InputFilePath |select -skip 2| select-string '}' -NotMatch|%{$_ -replace '"\s+(\-?\d+\.\d+)\s+(\-?\d+\.\d+)\s+(\-?\d+\.\d+)','"" ,, , , ,'}| %{$_ -split '"\s+,'} |%{$_ -replace '"\s+("\w+")', ' "  "YES"'}| %{$_ -replace '"\s+("\w+\s+")', ' "  "YES"'}|out-file $OutputFilePath
$data=Get-Content $OutputFilePath| select-string ',' 
$data=$data|%{$_ -replace '(,\s+0.00,\s+\-?\d+\.\d+\,\s+\d+\.\d+)',':'}| %{$_ -split ':'}
$headers=Get-Content $OutputFilePath| select-string '"' | Get-Unique
$counter=0
$data | %{if($_.length -eq 0){$_ -replace '', ($headers|Select-Object -index $counter) ;$counter=$counter+1 }else{$_} }|out-file $OutputFilePath

这是我的完整代码,但这个问题的重要部分是我开始分配变量的地方。感谢大家的帮助!