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