programing

파워셸을 사용하여 CRLF 교체

topblog 2023. 7. 27. 21:33
반응형

파워셸을 사용하여 CRLF 교체

편집자 참고: OP의 이후 논평으로 판단할 때, 이 질문의 요지는 다음과 같습니다.PowerShell에서 CRLF(윈도우즈 스타일) 줄 끝이 있는 파일을 LF 전용(유닉스 스타일) 파일로 변환하려면 어떻게 해야 합니까?

파워셸 스크립트는 다음과 같습니다.

 $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를 빈 문자열로 바꿀 수 있습니다.캐리지 리턴 라인 피드를 라인 피드로만 교체할 수 없습니다.하지만 이것은 효과가 없습니다.

다음은 Windows PowerShell v5.1 / PowerShell Core v6.2.0의 최신 답변입니다.

  • Andrew Savinh의 불운한 답변은, 받아들여졌음에도 불구하고, 이 글에서 근본적으로 결함이 있습니다(나는 그것이 고쳐지기를 바랍니다 - 댓글과 편집 내역에 그렇게 하기에 충분한 정보가 있습니다).

  • Ansgar Wiecher의 유용답변은 잘 작동하지만 직접적인 사용이 필요합니다.NET Framework(변경될 수 있지만 전체 파일을 메모리로 읽습니다.)의 직접 사용.NET Framework는 그 자체로는 문제가 되지 않지만 초보자에게는 마스터하기 어렵고 일반적으로 기억하기 어렵습니다.

  • PowerShell Core미래 버전에는 다음과 같은 기능이 도입될 수 있습니다.
    Convert-TextFile-LineEnding특정 새 줄 스타일로 텍스트 파일을 인플레이스 업데이트할 수 있는 매개 변수: GitHub 이슈 #6201을 참조하십시오.

PSv5+에서는 이제 PowerShell 네이티브 솔루션이 가능합니다. 다음과 같습니다.Set-Content 에서는 이를지니다를 합니다.-NoNewline스위치 - 플랫폼 네이티브 새[1] 라인의 원치 않는 추가를 방지합니다.

# Convert CRLFs to LFs only.
# Note:
#  * (...) around Get-Content ensures that $file is read *in full*
#    up front, so that it is possible to write back the transformed content
#    to the same file.
#  * + "`n" ensures that the file has a *trailing LF*, which Unix platforms
#     expect.
((Get-Content $file) -join "`n") + "`n" | Set-Content -NoNewline $file

위 사항은 다음에 의존합니다.Get-ContentCR 전용, CRLF 및 LF 전용 새 줄을 조합하여 사용하는 텍스트 파일을 한 줄씩 읽는 기능.

주의사항:

  • 입력 파일을 동일한 인코딩으로 다시 만들려면 입력 파일일치하도록 출력 인코딩지정해야 합니다.위의 명령은 출력 인코딩을 지정하지 않습니다. 지정하려면 ;을 사용하십시오.

  • 기본적으로, 사용하지 않음 -Encoding:

    • Windows PowerShell에서는 미국 영어 시스템의 Windows-1252와 같이 시스템의 단일 바이트 8비트 레거시 인코딩인 "ANSI" 인코딩을 사용할 수 있습니다.

    • PowerShell(코어) v6+에서는 BOM 없이 UTF-8 인코딩을 얻을 수 있습니다.

    • 입력 파일의 내용과 변환된 복사본은 메모리에 전체적으로 들어맞아야 합니다. 이는 큰 입력 파일에서는 문제가 될 수 있지만 텍스트 파일에서는 거의 문제가 되지 않습니다.

    • 입력 파일에 다시 쓰는 프로세스가 중단되면 파일이 손상될 위험이 적습니다.


사실 쓸 줄이 여러 개라면-NoNewline또한 두 줄 사이에 새 을 배치하지 않습니다. 그러나 현재의 경우 문자열이 하나만 작성되므로 이는 관련이 없습니다.

버전을 지정하지 않았습니다. Powershell v3를 사용하고 있는 것 같습니다.

사용해 보십시오.

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

편집자 참고 사항:mikez가 설명에서 지적했듯이, 에서는 원하지 않는 후행 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.

이렇게 하면 전체 파일이 메모리에 로드되므로 대용량 파일을 처리하려는 경우 다른 솔루션이 필요할 수 있습니다.

갱신하다

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가 댓글에서 지적한 함정을 피하기 위해 다른 파일을 사용합니다.> 실행이 시작되기 전에 대상 파일잘라냅니다.그러나 더 중요한 것은 이 솔루션도 원치 않을있는 후행 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.

하지만 메모리에 로드되는 것에 대해서는 같은 예약입니다.

가짜 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)

아래는 모든 파일을 재귀적으로 변환하는 나의 스크립트입니다.제외할 폴더 또는 파일을 지정할 수 있습니다.

$excludeFolders = "node_modules|dist|.vs";
$excludeFiles = ".*\.map.*|.*\.zip|.*\.png|.*\.ps1"

Function Dos2Unix {
    [CmdletBinding()]
    Param([Parameter(ValueFromPipeline)] $fileName)

    Write-Host -Nonewline "."

    $fileContents = Get-Content -raw $fileName
    $containsCrLf = $fileContents | %{$_ -match "\r\n"}
    If($containsCrLf -contains $true)
    {
        Write-Host "`r`nCleaing file: $fileName"
        set-content -Nonewline -Encoding utf8 $fileName ($fileContents -replace "`r`n","`n")
    }
}

Get-Childitem -File "." -Recurse |
Where-Object {$_.PSParentPath -notmatch $excludeFolders} |
Where-Object {$_.PSPath -notmatch $excludeFiles} |
foreach { $_.PSPath | Dos2Unix }

위의 @ricky89 및 @mklement0의 예를 기반으로 몇 가지 개선 사항을 포함한 다른 버전 추가:

처리할 스크립트:

  • 현재 폴더의 *.txt 파일
  • LF를 CRLF로 대체(Windows 줄 끝 부분에 대한 유닉스)
  • 결과 파일을 CR-to-CRLF 하위 폴더에 저장
  • 100MB 이상의 파일, PS v5에서 테스트됨.

LF-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.')
}

CMD의 경우 한 줄 LF 전용:

powershell -NoProfile -command "((Get-Content 'prueba1.txt') -join \"`n\") + \"`n\" | Set-Content -NoNewline 'prueba1.txt'"

그래서 당신은 .bat를 만들 수 있습니다.

다음은 매우 큰 파일을 빠르게 처리할 수 있습니다.

$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.')

언급URL : https://stackoverflow.com/questions/19127741/replace-crlf-using-powershell

반응형