[英]How to read multiple data sets from one .csv file in powershell
我有一個臨時記錄器,它(每天)讀取多個傳感器,並在每組日期/時間和溫度之前將數據與一大堆標題信息保存到單個.csv中。 該文件看起來像這樣:
"readerinfo","onlylistedonce"
"downloadinfo",YYYY/MM/DD 00:00:00
"timezone",-8
"headerstuff","headersuff"
"sensor1","sensorstuff"
"serial#","0000001"
"about15lines","ofthisstuff"
"header1","header2"
datetime,temp
datetime,temp
datetime,temp
"sensor2","sensorstuff"
"serial#","0000002"
"about15lines","ofthisstuff"
"header1","header2"
datetime,temp
datetime,temp
datetime,temp
"downloadcomplete"
我的目的是為每個傳感器提取日期/時間和溫度數據,並將其保存為新文件,以便我可以在其上運行一些基本統計信息(高/低/平均溫度)。 (如果我能以某種方式根據標頭信息中列出的序列號識別數據來自哪個傳感器,那將很漂亮,但這並不比將數據分成幾組重要。)日期/時間列表的長度因傳感器而異根據傳感器已錄制了多長時間以及傳感器的數量每天也在變化。 即使我可以將傳感器數據,標頭信息以及所有內容拆分為多個文件(包含傳感器),這也是一個不錯的開始。
從傳統意義上來說,這不是CSV文件。 鑒於您對文件內容的描述,我想您已經知道這一點。
根據您的示例數據,如果帶有datetime,temp
的行中確實沒有任何雙引號,則以下腳本應該起作用。 該腳本是自包含的,因為它可以內聯聲明示例數據。
重要說明 :您將需要修改包含$SensorList
變量的聲明的行。 您將必須使用傳感器的名稱填充此變量,或者您可以參數化腳本以接受傳感器名稱的數組。
更新 :我將腳本更改為參數化。
該腳本的結果如下:
腳本的內容應如下所示。 將腳本文件保存到文件夾,例如c:\\test\\test.ps1
,然后執行它。
# Declare text as a PowerShell here-string
$Text = @"
"readerinfo","onlylistedonce"
"downloadinfo",YYYY/MM/DD 00:00:00
"timezone",-8
"headerstuff","headersuff"
"sensor1","sensorstuff"
"serial#","0000001"
"about15lines","ofthisstuff"
"header1","header2"
datetime,tempfromsensor1
datetime,tempfromsensor1
datetime,tempfromsensor1
"sensor2","sensorstuff"
"serial#","0000002"
"about15lines","ofthisstuff"
"header1","header2"
datetime,tempfromsensor2
datetime,tempfromsensor2
datetime,tempfromsensor2
"downloadcomplete"
"@.Split("`n");
# Declare the list of sensor names
$SensorList = @('sensor1', 'sensor2');
$CurrentSensor = $null;
# WARNING: Clean up all CSV files in the same directory as the script
Remove-Item -Path $PSScriptRoot\*.csv;
# Iterate over each line in the text file
foreach ($Line in $Text) {
#region Line matches double quote
if ($Line -match '"') {
# Parse the property/value pairs (where double quotes are present)
if ($Line -match '"(.*?)",("(?<value>.*)"|(?<value>.*))') {
$Entry = [PSCustomObject]@{
Property = $matches[1];
Value = $matches['value'];
};
if ($matches[1] -in $SensorList) {
$CurrentSensor = $matches[1];
Write-Host -ForegroundColor Green -Object ('Current sensor is: {0}' -f $CurrentSensor);
}
}
}
#endregion Line matches double quote
#region Line does not match double quote
else {
# Parse the datetime/temp pairs
if ($Line -match '(.*?),(.*)') {
$Entry = [PSCustomObject]@{
DateTime = $matches[1];
Temp = $matches[2];
};
# Write the sensor's datetime/temp to its file
Add-Content -Path ('{0}\{1}.csv' -f $PSScriptRoot, $CurrentSensor) -Value $Line;
}
}
#endregion Line does not match double quote
}
使用您提供的數據樣本,此腳本的輸出如下:
C:\\ sensoroutput_20140204.csv
sensor1,datetime,temp
sensor1,datetime,temp
sensor1,datetime,temp
sensor2,datetime,temp
sensor2,datetime,temp
sensor2,datetime,temp
我相信這就是您要尋找的。 這里的假設是換行符。 通過使用2個新行字符作為分隔符, get-content
行正在讀取數據並將其分為“集合”。 我選擇使用環境(Windows)的換行符。 您的源文件可能具有不同的換行符。 您可以使用Notepad ++查看它們是哪個字符,例如\\ r \\ n,\\ n等。
$newline = [Environment]::NewLine
$srcfile = "C:\sensordata.log"
$dstpath = 'C:\sensoroutput_{0}.csv' -f (get-date -f 'yyyyMMdd')
# Reads file as a single string with out-string
# then splits with a delimiter of two new line chars
$datasets = get-content $srcfile -delimiter ($newline * 2)
foreach ($ds in $datasets) {
$lines = ($ds -split $newline) # Split dataset into lines
$setname = $lines[0] -replace '\"(\w+).*', '$1' # Get the set or sensor name
$lines | % {
if ($_ -and $_ -notmatch '"') { # No empty lines and no lines with quotes
$data = ($setname, ',', $_ -join '') # Concats set name, datetime, and temp
Out-File -filepath $dstpath -inputObject $data -encoding 'ascii' -append
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.