我使用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)
那里有很多,而且一切都像它应该的那样。我只需要另一种整理重复的方法。想法?
答案 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
这是我的完整代码,但这个问题的重要部分是我开始分配变量的地方。感谢所有帮助人员!