2012-08-30 92 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