我有一个单列的CSV文件。根据我的机器有多少个故障代码,此列将具有不同数量的代码(最多10个子列 - 请参见下面的示例)。我想操纵此CSV,以便输出是唯一故障代码的干净列表已经发生了。
示例CSV文件(sample.csv):
ActiveFaults
00:1523 00:1345 00:1343 90:1344
00:1523 00:1345 00:1343 90:1344
00:1523 00:1345 00:1343 90:1344
00:1523 00:1345 00:1343 90:1344
00:1523 00:1345 00:1343 90:1344 90:5900 90:8988
00:1523 00:1345 00:1343 90:1344 90:5900 90:8988
BA:8797 BA: 1330
理想输出将是以下格式的CSV文件:
IdealOutput.csv
UniqueActiveFaults
00:1523
00:1345
00:1343
90:1344
90:5900
90:8988
BA:8797
BA:1330
有什么想法可以做到这一点?我尝试了几种方法(使用-Sort,-Group等...但没有一种方法可以正常工作)谢谢。
答案 0 :(得分:3)
停止将该文件视为CSV。
只需读入一个字符串,用空格拆分并将其传递给Sort-Object -Unique
:
$Values = (Get-Content .\sample.csv -Raw) -split '\s+' | Where-Object {$_ -like '*:*'}
"UniqueActiveFaults" |Out-File .\IdealOutput.csv
$Values | Sort-Object -Unique | Out-File .\IdealOutput.csv
-split
运算符将正则表达式作为右侧操作数,在本例中为\s+
。 \s
是"空白"的缩写。字符类,+
表示"匹配前面一个或多个字符"
如果文件很大,您可以使用第一个语句中的ReadCount
参数将处理拆分为块:
Get-Content .\sample.csv -ReadCount 100 |ForEach-Object {$_ -split '\s+'}
如果文档中的其他位置存在:
,并且所需的值始终为
[2 character prefix]:[numerical]
您可以通过将Where-Object
过滤器更改为:
{$_ -match '.{2}:\d+'}
答案 1 :(得分:2)
由于马蒂亚斯不喜欢我的建议,我会在这里展示我的意思:
false
输出如下:
Import-Csv .\Sample.csv |
% { $_.ActiveFaults -split '\s+' } |
Sort-Object -Unique |
Select-Object @{name='UniqueActiveFaults'; expr={ $_ } } |
Export-Csv IdealOutput.csv -NoTypeInformation
如果输入真的很大并且上面的代码无法有效处理它,我会尝试将值汇总到.NET HashSet中代替Sort-Object。
答案 2 :(得分:0)
@ECHO Off
SETLOCAL
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
(
ECHO(UniqueAciveFaults
FOR /f "delims=" %%a IN (q29884835.txt) DO FOR %%b IN (%%a) DO SET "$%%b=y"
FOR /f "delims=$=" %%a IN ('set $^|find ":"') DO ECHO(%%a
)>u:\newfile.csv
GOTO :EOF
我使用了一个名为q29884835.txt
的文件,其中包含我的测试数据。
制作u:\ newfile.csv
嗯 - 它显然不是PowerShell,但它确实有效。
第一个for
清除任何从$
开始的环境变量。通常没有,所以可能不需要它。
第二行for
行读取文件,然后为每个元素设置一个变量$elementcontents
到y
(事实上,它设置为某些东西很重要,< em>某事不是)
第三行for
行选择包含$
和:
的集合echo
变量的那一部分。