web-dev-qa-db-fra.com

Set-Content ajoute une nouvelle ligne (saut de ligne, CRLF) à la fin de mon fichier

Mon fichier de configuration d'origine (web1.config) n'a pas de ligne supplémentaire et lorsqu'il est affiché dans le bloc-notes (affichant tous les caractères), il ressemble à:

enter image description here

 <?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" />
  </system.web>
  <appSettings>
    <add key="myConnectionString" value="server=localhost;database=myDb;uid=myUser;password=myPass;" />
  </appSettings>
</configuration>

Maintenant, je dois appliquer le script pour changer le nom de ma base de données en quelque chose d'autre qui ressemble à:

 Move-Item "web1.config" "webtemp.config"
Get-Content "webtemp.config" | ForEach-Object {$_ -replace "database=myDb;", "database=newDb;"} |Set-Content "web1.config" -Force
Remove-Item "webtemp.config"
Write-Output('Settings Changed')

Ainsi, le nouveau fichier (web1.config) généré ressemble à:

enter image description here

Remarquez la ligne supplémentaire ajoutée à la fin du fichier (ce qui n'est absolument pas nécessaire). J'ai essayé toutes les autres options telles que: - en utilisant l'api hors fichier - en utilisant .net IO méthode System.IO .StreamWriter - en utilisant l'indicateur -nonewline (il convertit les 10 lignes en une seule ligne) - en utilisant différentes options de codage - a essayé de remplacer\r\n en\r (ne fonctionne pas car set-content génère toujours le crlf)

J'utilise PowerShell v5.1.

16
OmGanesh

tl; dr ( PSv5 +; voir en bas pour les anciennes versions):

(Get-Content webtemp.config) -replace "database=myDb;","database=newDb;" -join "`n" |
  Set-Content -NoNewline -Force web1.config

Remarque: Remplacez "`n" Par "`r`n" Si vous voulez des fins de ligne CRLF de style Windows plutôt que des fins de ligne LF uniquement Unix (PowerShell et de nombreux utilitaires peuvent gérer les deux).


Dans PSv5 + , Set-Content Prend en charge le commutateur -NoNewline, qui demande à Set-Content de ne pas ajouter de nouvelle ligne (saut de ligne) après chaque objet d'entrée . Il en va de même pour les applets de commande Add-Content Et Out-File.

En d'autres termes: Set-Content -NoNewline concatène directement les représentations de chaîne de tous ses objets d'entrée :

> 'one', 'two' | Set-Content -NoNewline tmp.txt; Get-Content tmp.txt
onetwo

Si ce que vous passez à Set-Content -NoNewline Est un chaîne unique qui a déjà des nouvelles lignes intégrées, vous pouvez l'utiliser tel quel et obtenir le résultat souhaité:

> "one`ntwo" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
one
two?

Notez que Get-Content -Raw Lit le fichier dans son ensemble, tel quel (à part le décodage des caractères) et le fait que ? Apparaît directement après two implique que le fichier n'a pas de nouvelle ligne de fin.

Dans votre cas, puisque vous traitez les lignes d'entrée un par un (via Get-Content sans-Raw) Et donc sortir un tableau de lignes (chaînes), vous devez d'abord les joindre avec une nouvelle ligne comme séparateur - entre lignes uniquement - et passez le résultat à Set-Content -NoNewline, comme indiqué en haut; voici un exemple simplifié:

> ('one', 'two') -join "`n" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
one
two?

'one', 'two' Est un tableau de chaînes à deux éléments qui remplace votre commande de traitement ligne par ligne.

Note d'encodage:

Dans Windows PowerShell, Set-Content Produit par défaut des fichiers codés "ANSI", basés sur la page de code à un octet héritée de votre système.
Pour contrôler explicitement l'encodage, utilisez le paramètre -Encoding.


Dans PSv4 - , une solution qui utilise le .NET Framework est nécessaire:

> [System.IO.File]::WriteAllText('tmp.txt', ('one', 'two') -join "`n"); "$(Get-Content -Raw tmp.txt)?"
one
two?

Notez que [System.IO.File]::WriteAllText() , en l'absence d'argument de codage, par défaut est UTF-8 sans nomenclature.
Passez l'instance d'encodage [System.Text.Encoding] Souhaitée en tant que 3e argument selon les besoins.

18
mklement0

Je n'ai jamais remarqué cela, alors j'ai fait une recherche rapide et j'ai trouvé:

set-content ajoute des sauts de ligne par défaut

La solution suggérée consiste à coder votre contenu en octets, puis à utiliser Set-Content avec le paramètre -Encoding.

Set-Content test.txt ([byte[]][char[]] "test") -Encoding Byte

Je l'ai testé moi-même afin que je puisse confirmer que cela fonctionne.

2
SteloNLD