2016-10-06 18 views
0

入力ファイルは固定幅のtxtファイルです。私のクライアントは通常、Excelでそれを開き、手動で列区切りを指定します。私はCSVとして解析してXLSなどで保存できるように、特定の空白をカンマで置き換えることを望んでいます。固定幅txtファイルをCSV/set-contentまたはout-file -appendに変換しますか?

$columBreaks = 20, 35, 50, 80, 100, 111, 131, 158, 161, 167, 183 
[array]::Reverse($columBreaks) #too lazy to re-write array after finding out I need to iterate in reverse 

$files = get-childitem ./ |where-object {$_.Name -like "FileFormat*.txt"} 

foreach($file in $files) 
{ 
    $name = $file.Name.split(".") 
    $csvFile = $name[0]+".csv" 
    if (!(get-childitem ./ |where-object {$_.Name -like $csvFile})) #check whether file has been processed 
    { 
     $text = (gc $file) 
     foreach ($line in $text) 
     { 
      foreach ($pos in $columBreaks) 
      { 
       #$line.Substring($char-1,3).replace(" ", ",") 
       $line = $line.Insert($pos,",") 
       #out-file -append? 
      } 
     } 
    } 
    #set-content? 
} 

このコンテンツを書くにはどのような方法が最適ですか?私はセットコンテンツを使うことを望んでいましたが、私たちは行単位で処理しているので考えられませんので、セットコンテンツ用の配列を作るか、繰り返しごとに追加します。これを行うより効率的な方法はありますか?

答えて

1

セットコンテンツは、細かい調整を行っても問題なく動作します。ここでは(これはあなたの外側のforeachループ内のすべてです)、それが動作するはず方法の例です:「」

$csvFile = $file.BaseName 
    if (!(get-childitem ./ |where-object {$_.Name -like $csvFile})) #check whether file has been processed 
    { 
     (gc $file | foreach { 
       $_.Insert($columBreaks[0],",").Insert($columBreaks[1],",").Insert($columBreaks[2],",").` 
       Insert($columBreaks[3],",").Insert($columBreaks[4],",").Insert($columBreaks[5],",").` 
       Insert($columBreaks[6],",").Insert($columBreaks[7],",").Insert($columBreaks[8],",").` 
       Insert($columBreaks[9],",").Insert($columBreaks[10],",") 
      }) | set-content $csvFile #note parenthesis around everything that gets piped to set-content 
    } 

ところで、代わりにファイル名を分割するのは、あなただけなしで名前を取得することができます拡張子を使用して$file.BaseName

$csvFile = $file.BaseName + ".csv" 
+0

basename tipをありがとう。セット内容は私に空のパイプエラーを与えます。 –

+0

私は最初にif文を見逃しました。 ifブロックの中でset-contentビットを動かすだけでいいはずです(foreach($ text in $ text)の直後) – morgb

+0

foreachからの配管はまったく動作しないと思います。 foreach-objectを使っている例がありますが、それに必要なフォーマットで内部ループを変換するのに苦労しました –

0

ここに作業コードです。少数のバグ修正。

CD 'C:\\FOLDERPATH\' 
$filter = "FILE_NAME_*.txt" 

$columns = 11,22,32,42,54 

# DO NOT NEED TO REVERSE [array]::Reverse($columns) #too lazy to re-write array after finding out I need to iterate in reverse 

$files = get-childitem ./ |where-object {$_.Name -like $filter} 
$newDelimiter = '|' 

foreach($file in $files) 
{ 
    $file 

    $csvFile = 'C:\\FOLDERPATH\NEW_' + $file.BaseName + '.txt' 
    if (!(get-childitem ./ |where-object {$_.Name -like $csvFile})) #check whether file has been processed 
    { 

     $content | ForEach { 
      $line = $_ 
      $counter = 0 
      $columns | ForEach { 
       $line = $line.Insert($_+$counter, $newDelimiter) 
       $counter = $counter + 1 
       } 
      $line = $line.Trim($newDelimiter) 
      $line 
     } | set-content $csvFile 
    } 

} 
関連する問題