Remplacer CRLF par powershell

note de l'Éditeur: a en juger par les commentaires ultérieurs de L'OP, l'essentiel de cette question Est: comment convertir un fichier avec les terminaisons de ligne CRLF (style Windows) en un fichier LF (style Unix) dans PowerShell?

Voici mon script powershell:

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

avec ce code je peux remplacer 2 par 3, 1 par 7 et 9 par une chaîne vide. Je ne peux pas remplacer l'alimentation de la ligne de retour de chariot par l'alimentation de la ligne. Mais ce ne marche pas.

18
demandé sur mklement0 2013-10-02 03:35:46

5 réponses

vous n'avez pas spécifié la version, je suppose que vous utilisez Powershell v3.

essaye ceci:

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

note de l'Éditeur: comme le souligne mike z dans les commentaires,Set-Content ajoute un CRLF arrière, ce qui n'est pas désiré. Vérifiez avec: 'hi' > t.txt; (Get-Content -Raw t.txt).Replace("`r`n","`n") | Set-Content t.txt; (Get-Content -Raw t.txt).EndsWith("`r`n"), ce qui donne $True.

notez que cela charge l'ensemble du fichier en mémoire, donc vous pourriez vouloir une solution différente si vous voulez traiter énorme fichier.

UPDATE

Cela peut fonctionner pour la v2 (désolé nulle part pour test):

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

note de l'Éditeur: Notez que cette solution (maintenant) écrit dans un fichier différent et n'est donc pas équivalent à la solution v3 (encore imparfaite). (Un fichier différent est ciblé pour éviter le piège Ansgar Wiechers souligne dans les commentaires: en utilisant >tronque le fichier cible avant début de l'exécution). Plus important encore: cette solution aussi ajoute un CRLF arrière, ce qui n'est pas désiré. Vérifiez avec 'hi' > t.txt; (Get-Content t.txt) -join "`n" > t.NEW.txt; [io.file]::ReadAllText((Convert-Path t.NEW.txt)).endswith("`r`n"), ce qui donne $True.

même réserve sur le fait d'être chargé en mémoire.

23
répondu Andrew Savinykh 2018-02-22 02:06:06

autre solution que de ne pas ajouter une fausse 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)
12
répondu Ansgar Wiechers 2013-10-02 08:09:07

Ceci est un état de l'union de répondre à tant de Windows PowerShell v5.1 / PowerShell de Base v6.0.1:

  • la réponse malheureuse D'Andrew Savinykh, bien qu'il soit accepté, est,de cette écriture, fondamentalement imparfait (j'espère que c'est résolu - il y a assez d'information dans les commentaires et dans l'historique de modification à faire).

  • Ansgar Wiecher de réponse utile fonctionne bien, mais nécessite l'utilisation directe du .net Framework (et lit tout le fichier en mémoire, bien que susceptibles d'être modifiés). L'utilisation directe du .net Framework n'est pas un problème en soi, mais est plus difficile à maîtriser pour les novices et difficile à se souvenir en général.

  • avenir version de PowerShell Core (en date de rédaction de ce document: v6.0.2) aura un

    Convert-TextFile applet de commande avec un -LineEnding paramètre permettant la mise à jour en place des fichiers texte avec un style newline spécifique, comme discuté GitHub.

PSv5+,PowerShell-des solutions natives sont maintenant possibles, parce que Set-Content supporte maintenant le -NoNewline switch, qui empêche l'ajout indésirable d'une plateforme-native newline [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

ci-dessus s'appuie sur Get-Contentla capacité de lire un fichier texte qui utilise toute combinaison de CR-only, CRLF, et LF-only les sauts de ligne, ligne par ligne.

mises en garde:

  • Vous devez spécifiez le codage de sortiecorrespond au fichier d'entrée afin de la recréer avec le même encodage. La commande ci-dessus ne spécifie pas d'encodage de sortie; pour ce faire, utilisez -Encoding;sans -Encoding:

    • Windows PowerShell, vous obtiendrez "ANSI" encodage, l'encodage d'un seul octet, 8 bits de votre système, tel que Windows-1252 sur les systèmes US-English.
    • Noyau PowerShell, vous obtiendrez encodage UTF-8 sans une NOMENCLATURE.
  • le contenu du fichier d'entrée ainsi que sa copie transformée devez tenir en mémoire ensemble, qui peut être problématique avec de gros fichiers d'entrée.

  • il y a un risque de corruption des fichiers, si quelque chose tourne mal avant que le nouveau contenu puisse être (entièrement) réécrit dans le fichier d'entrée.


[1] en fait, s'il y a plusieurs chaînes d'écrire, -NoNewline aussi, ne place pas un retour à la ligne entre; dans le cas présent, cependant, ceci n'est pas pertinent, parce que seulement chaîne est écrite.

9
répondu mklement0 2018-03-20 13:32:19

ajout d'une autre version basée sur l'exemple ci-dessus de @ricky89 et @mklement0 avec quelques améliorations:

Script de traitement:

  • *.fichiers txt dans le dossier courant
  • remplacer LF par CRLF (fin de ligne Unix à Windows)
  • sauvegarder les fichiers résultants de CR-à-CRLF sous-dossier
  • testé sur 100 MO+ fichiers, 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.')
}
1
répondu Rod 2017-05-18 05:30:09

La suite sera capable de traiter de très gros fichiers rapidement.

$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
répondu ricky89 2016-12-21 21:01:42