2012-08-30 88 views
1

我與格式的文件重新格式化文件,以管格式使用PowerShell

first:web 
last:site 
age:99 

first:stack 
last:overflow 
age: 88 

我試圖將其轉換爲這種格式

first|last|age 
web|site|99 
stack|overflow|88 

到目前爲止,這是我所使用的代碼得到它在一條線,但我想不通的語法來循環它,並打破它

$TextLocation = "data.txt" 
$Writefile = "results.txt" 
$FileLocation = "C:\Users\" 
$SearchStr1 = "First:" 
$SearchStr2 = "Last:" 
$SearchStr3 = "Age:" 
$SearchStr4 = "" 


#Get content 
$a =Get-Content $TextLocation | 

#Find search strings and replace with pipes 

Foreach-Object { 
    $_ -replace $SearchStr1 , "|" ` 
    -replace $SearchStr2, "|" ` 
    -replace $SearchStr3, "|" ` 
    -replace$SearchStr4, "|" ` 

} | 

# join all lines 
$a -join "" 

#Break after every 4th pipe 

謝謝

回答

4

您可以使用選擇字符串cmdlet來查找在「第一」一個macth並獲得該行加上後兩行:

'first|last|age' 

Get-ChildItem .\file.txt | Select-String '^first:' -Context 0,2 | ForEach-Object{ 

    $f = $_.Line.Split(':') 
    $l = $_.Context.PostContext[0].Split(':') 
    $a = $_.Context.PostContext[1].Split(':') 

    $f[1],$l[1],$a[1] -join '|' 

} 

first|last|age 
web|site|99 
stack|overflow| 88 
+0

比我的好多了。雖然我認爲如果我這樣做,我仍然會創建一個自定義對象的集合並將其傳遞給export-csv。這會增加資源開銷,但如果您需要沿着其他信息執行任何邏輯或搬運,則會更靈活。 – EBGreen

+0

我同意,這取決於。我可以看到客觀結果的價值。 –

+0

太棒了!效果很好。我同意自定義對象以及進一步的修補。我還會在那裏放置一行代碼以消除多餘的空白。謝謝! – david

0

會有多種方式來處理這個問題。這裏是一個:

$result = @() 
$temp = New-Object PSCustomObject -Prop @{'first' = ''; 'last' = ''; 'age' = ''} 
foreach($line in Get-Content C:\PATH\TO\INPUT.txt){ 
    if($line.StartsWith('first')){ 
     $temp.first = $line.Split(':')[1] 
    }elseif($line.StartsWith('last')){ 
     $temp.last = $line.Split(':')[1] 
    }elseif($line.StartsWith('age')){ 
     $temp.age = $line.Split(':')[1] 
    }else{ 
     $result += $temp 
     $temp = New-Object PSCustomObject -Prop @{'first' = ''; 'last' = ''; 'age' = ''} 
    } 
} 
$result += $temp 
$result | Export-CSV C:\PATH\TO\RESULT.csv -NoTypeInformation -NoHeader -Delimiter '|' 

這不是我真正想做的,但它是骨架,應該讓你開始。至少你可能想要確保它更好地處理文件中的第一個和最後一個記錄。我只是以這種方式將它打成一個示範。

0

這是一個相當通用的解決方案:

$contents = gc C:\test.txt 
$printedHeader = $false; 
for ($i=0; $i -lt $contents.Length; $i++){ 
    $line = $contents[$i]; 
    $keyVal = $line.Split(':',2) 
    $keys += $keyVal[0]; 
    $vals += $keyVal[1];  

    if ($contents[$i] -eq "" -or $i -eq $contents.Length - 1){ 
     if ($printedHeader -eq $false){ 
      $keys -join "|" 
      $printedHeader = $true; 
     }  
     $vals -join "|"  
     $vals = @(); 
     $keys = @();   
    } 
} 
0

另一種選擇:

function Get-Data($Path='c:\data') { 

     $content = (Get-Content $Path | where {$_}) -split ':' 
     for($i=0;$i -lt $content.length;$i++) { 
      if(!$i) { 'first|last|age' } 
      if($i % 2 -eq 1) { 
       $content[$i],$content[$i+2],$content[$i+4] -join '|' 
       $i+=5 
      } 
     } 
    } 

    PS II> Get-Data c:\scripts\data.txt 

    first|last|age 
    web|site|99 
    stack|overflow| 88