web-dev-qa-db-ja.com

PowerShellを使用してCRLFを交換する

編集者のメモ:OPによる後のコメントから判断すると、この質問の要旨は次のとおりです:どのように変換できますかPowerShellでLFのみ(Unixスタイル)ファイルにCRLF(Windowsスタイル)行末を持つファイル?

ここに私のpowershellスクリプトがあります:

 $original_file ='C:\Users\abc\Desktop\File\abc.txt'
 (Get-Content $original_file) | Foreach-Object {
 $_ -replace "'", "2"`
-replace '2', '3'`
-replace '1', '7'`
-replace '9', ''`
-replace "`r`n",'`n'
} | Set-Content "C:\Users\abc\Desktop\File\abc.txt" -Force

このコードを使用すると、2を3に、1を7に、9を空の文字列に置き換えることができます。キャリッジリターンラインフィードをラインフィードだけに置き換えることはできません。しかし、これは機能しません。

26
Angel_Boy

バージョンを指定していません。Powershellv3を使用していると思われます。

これを試して:

_$path = "C:\Users\abc\Desktop\File\abc.txt"
(Get-Content $path -Raw).Replace("`r`n","`n") | Set-Content $path -Force
_

編集者のメモ:マイクzがコメントで指摘しているように、_Set-Content_は末尾のCRLFを追加します。これは望ましくありません'hi' > t.txt; (Get-Content -Raw t.txt).Replace("`r`n","`n") | Set-Content t.txt; (Get-Content -Raw t.txt).EndsWith("`r`n")で検証します。これにより、_$True_が生成されます。

これにより、ファイル全体がメモリにロードされるため、巨大なファイルを処理する場合は別のソリューションが必要になる場合があります。

[〜#〜] update [〜#〜]

これはv2で動作する可能性があります(テストする場所はありません):

_$in = "C:\Users\abc\Desktop\File\abc.txt"
$out = "C:\Users\abc\Desktop\File\abc-out.txt"
(Get-Content $in) -join "`n" > $out
_

編集者のメモ:このソリューション(今)は異なるファイルに書き込むため、(まだ欠陥がある) )v3ソリューション。 (Ansgar Wiechersがコメントで指摘している落とし穴を避けるために、別のファイルがターゲットになっています:_>_truncatesを使用してターゲットファイルbefore実行が開始されます)。ただし、さらに重要なことは、このソリューションも望ましくない末尾のCRLFを追加するです。 'hi' > t.txt; (Get-Content t.txt) -join "`n" > t.NEW.txt; [io.file]::ReadAllText((Convert-Path t.NEW.txt)).endswith("`r`n")で確認すると、_$True_が生成されます。

ただし、メモリへのロードについても同様です。

26
Andrew Savinykh

偽のCR-LFを追加しない代替ソリューション:

$original_file ='C:\Users\abc\Desktop\File\abc.txt'
$text = [IO.File]::ReadAllText($original_file) -replace "`r`n", "`n"
[IO.File]::WriteAllText($original_file, $text)
15
Ansgar Wiechers

@ ricky89と@ mklement0による上記の例に基づいて、いくつかの改善を加えた別のバージョンを追加します:

処理するスクリプト:

  • *現在のフォルダー内の.txtファイル
  • LFをCRLF(UnixからWindowsの行末まで)に置き換えます
  • 結果のファイルをCR-to-CRLFサブフォルダーに保存します
  • 100 MB以上のファイル、PS v5でテスト済み。

LF-to-CRLF.ps1:

# get current dir
$currentDirectory = Split-Path $MyInvocation.MyCommand.Path -Parent

# create subdir CR-to-CRLF for new files
$outDir = $(Join-Path $currentDirectory "CR-to-CRLF")
New-Item -ItemType Directory -Force -Path $outDir | Out-Null

# get all .txt files
Get-ChildItem $currentDirectory -Force | Where-Object {$_.extension -eq ".txt"} | ForEach-Object {
  $file = New-Object System.IO.StreamReader -Arg $_.FullName
  # Resulting file will be in CR-to-CRLF subdir
  $outstream = [System.IO.StreamWriter] $(Join-Path  $outDir $($_.BaseName + $_.Extension))
  $count = 0 
  # read line by line, replace CR with CRLF in each by saving it with $outstream.WriteLine
  while ($line = $file.ReadLine()) {
        $count += 1
        $outstream.WriteLine($line)
    }
  $file.close()
  $outstream.close()
  Write-Host ("$_`: " + $count + ' lines processed.')
}
1
Rod

以下は、非常に大きなファイルを迅速に処理することができます。

$file = New-Object System.IO.StreamReader -Arg "file1.txt"
$outstream = [System.IO.StreamWriter] "file2.txt"
$count = 0 

while ($line = $file.ReadLine()) {
      $count += 1
      $s = $line -replace "`n", "`r`n"
      $outstream.WriteLine($s)
  }

$file.close()
$outstream.close()

Write-Host ([string] $count + ' lines have been processed.')
0
ricky89