在PowerShell中进一步指定Select -unique

时间:2015-08-11 22:14:02

标签: powershell select unique

我使用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,

这是我想要的格式。正如你所看到的,我把所有标签都变成了单个标题,然后摆脱了ALBENI F2,因为它是F1的重复。我的问题是,为了实现这一目标,我使用了select-object -unique。根据需要,它可以删除所有重复的标题和重复数据集。但是,它还删除了其他完全不同的标签上的重复数据点。这是无法接受的;因此,我需要一种方法来摆脱重复的标签和数据集,同时将所有数据点保留在唯一标签上,即使这些数据点与其他标签的数据点相同。

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

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

那里有很多,而且一切都像它应该的那样。我只需要另一种整理重复的方法。想法?

2 个答案:

答案 0 :(得分:0)

我将采取不同的方法,将您的数据转换为可以更轻松过滤的对象:

this.collection.parse = function (response) {
    return response.results;
};

this.collection.fetch();

现在您拥有一组具有属性的对象,您可以根据需要进行过滤,例如:

$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 ' '

为了更好的可读性,您可能希望通过管道$obj | Where-Object { $_.40028 -eq 40028 } 来了解这是如何工作的。

从您的问题中您有点不清楚您最终想要摆脱这种情况,因此很难展示更具体的问题。如果你有每个列的标题,它也会有所帮助,因为它会产生更有意义的属性名称。

说明

Format-Table

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

我们告诉$data -replace ' {2,}', ' ' | ConvertFrom-Csv -Delimeter ' ' 我们使用单个空格作为分隔符,然后它发挥其魔力。它理解引用的字段,所以这里效果很好。

如果您有标题,可以使用ConvertFrom-Csv指定标题,以便生成的属性具有良好的名称。

答案 1 :(得分:0)

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

[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+)','"" ,, $1, $2, $3,'}| %{$_ -split '"\s+,'} |%{$_ -replace '"\s+("\w+")', ' " $1 "YES"'}| %{$_ -replace '"\s+("\w+\s+")', ' " $1 "YES"'}|out-file $OutputFilePath
$data=Get-Content $OutputFilePath| select-string ',' 
$data=$data|%{$_ -replace '(,\s+0.00,\s+\-?\d+\.\d+\,\s+\d+\.\d+)',':$1'}| %{$_ -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

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