Ändern der Standardausgabecodierung von PowerShell in UTF-8

102

Wenn Sie die Ausgabe eines Befehls in eine Datei umleiten oder in eine andere Datei in PowerShell weiterleiten, lautet die Codierung standardmäßig UTF-16, was nicht sinnvoll ist. Ich möchte es auf UTF-8 ändern.

Dies kann von Fall zu Fall erfolgen, indem die >foo.txtSyntax durch ersetzt wird. Es | out-file foo.txt -encoding utf8ist jedoch umständlich, dies jedes Mal wiederholen zu müssen.

Die dauerhafte Möglichkeit, Dinge in PowerShell festzulegen, besteht darin, sie \Users\me\Documents\WindowsPowerShell\profile.ps1einzufügen. Ich habe überprüft, ob diese Datei beim Start tatsächlich ausgeführt wird.

Es wurde gesagt, dass die Ausgabecodierung mit eingestellt werden kann, $PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'}aber ich habe dies versucht und es hatte keine Auswirkung.

https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/, das $OutputEncodingauf den ersten Blick so aussieht, als ob es relevant sein sollte, aber dann davon spricht, dass die Ausgabe codiert wird in ASCII, was nicht das ist, was tatsächlich passiert.

Wie stellen Sie PowerShell für die Verwendung von UTF-8 ein?

rwallace
quelle

Antworten:

158

Hinweis: Für Windows PowerShell gilt Folgendes .
Im nächsten Abschnitt finden Sie die plattformübergreifende PowerShell Core (v6 +) Edition.

  • Auf PSv5.1 oder höher , wo >und >>effektiv Aliase sind Out-File, können Sie die Standardcodierung für Set >/ >>/ Out-Fileüber die $PSDefaultParameterValuesEinstellungsvariablen :

    • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
  • Auf PSv5.0 oder unten , Sie nicht kann die Codierung für ändern >/>> , aber auf PSV3 oder höher , die obige Technik tut Arbeit für explizite AnrufeOut-File .
    (Die $PSDefaultParameterValuesPräferenzvariable wurde in PSv3.0 eingeführt.)

  • Auf PSv3.0 oder höher , wenn Sie wollen die Standardeinstellung für die Codierung aller Cmdlets, unterstützen
    einen -EncodingParameter
    (die in PSv5.1 + enthält >und >>), zu verwenden:

    • $PSDefaultParameterValues['*:Encoding'] = 'utf8'

Wenn Sie diesen Befehl in Ihre$PROFILE Cmdlets einfügen, z. B. Out-FileundSet-Content verwenden standardmäßig die UTF-8-Codierung. Beachten Sie jedoch, dass dies eine sitzungsglobale Einstellung ist , die sich auf alle Befehle / Skripte auswirkt, die keine explizite Codierung angeben.

Stellen Sie in ähnlicher Weise sicher, dass Sie solche Befehle in Ihre Skripte oder Module aufnehmen, die sich genauso verhalten sollen , damit sie sich auch dann gleich verhalten, wenn sie von einem anderen Benutzer oder einem anderen Computer ausgeführt werden.

Vorsichtsmaßnahme : PowerShell ab Version 5.1, ausnahmslos UTF-8-Dateien mit einer (Pseudo-) Stückliste , was nur in der Windows- Weltüblich ist. Unix- basierte Dienstprogramme erkennen diese Stückliste nicht (siehe unten). In diesem Beitrag finden Sie Problemumgehungen, mit denen UTF-8-Dateien ohne Stückliste erstellt werden.

Eine Zusammenfassung des äußerst inkonsistenten Standard-Zeichencodierungsverhaltens in vielen Windows PowerShell-Standard-Cmdlets finden Sie im unteren Abschnitt.


Die automatische $OutputEncodingVariable hat keine Beziehung zueinander und gilt nur für die Kommunikation von PowerShell mit externen Programmen (welche Codierung PowerShell beim Senden von Zeichenfolgen an diese verwendet). Sie hat nichts mit der Codierung zu tun, die die Ausgabeumleitungsoperatoren und PowerShell-Cmdlets zum Speichern in Dateien verwenden.


Optionales Lesen: Die plattformübergreifende Perspektive: PowerShell Core :

PowerShell ist jetzt über seinen PowerShell Core plattformübergreifend Edition, deren Codierung - sinnvollerweise - standardmäßig UTF-8 ohne Stückliste gemäß Unix-ähnlichen Plattformen verwendet.

  • Dies bedeutet , dass Sourcecode - Dateien ohne BOM angenommen werden UTF-8, und mit sein >/ Out-File/ Set-ContentStandardwert BOM-weniger UTF-8; explizite Verwendung derutf8 -Encoding Arguments wird auch UTF-8 ohne Stückliste erstellt. Sie können jedoch auch Dateien mit der Pseudo-Stückliste mit dem utf8bomWert erstellen .

  • Wenn Sie PowerShell-Skripte mit einem Editor auf einer Unix-ähnlichen Plattform erstellen und heutzutage sogar auf Windows mit plattformübergreifenden Editoren wie Visual Studio Code und Sublime Text *.ps1erstellen , enthält die resultierende Datei normalerweise keine UTF-8-Pseudo-Stückliste:

    • Dies funktioniert gut mit PowerShell Core .
    • Unter Windows PowerShell kann es zu Problemen kommen , wenn die Datei Nicht-ASCII-Zeichen enthält. Wenn Sie in Ihren Skripten Nicht-ASCII-Zeichen verwenden müssen, speichern Sie diese als UTF-8 mit Stückliste .
      Ohne die Stückliste interpretiert Windows PowerShell Ihr Skript (falsch) als in der alten "ANSI" -Codepage codiert (bestimmt durch das Systemgebietsschema für Anwendungen vor Unicode, z. B. Windows-1252 auf US-englischen Systemen).
  • Im Gegensatz dazu werden Dateien , die zu tun haben den UTF-8 pseudo-BOM problematisch sein kann , auf Unix-ähnliche Plattformen, da sie Ursache Unix - Dienstprogramme wie cat, sedund awk- und sogar einige Editoren wie gedit- zu dem Pseudo-BOM passieren , das heißt, um es als Daten zu behandeln .

    • Dies ist möglicherweise nicht immer ein Problem, kann es aber definitiv sein, z. B. wenn Sie versuchen, eine Datei in eine Zeichenfolge bashmit beispielsweise text=$(cat file)oder zu lesentext=$(<file) - der resultierenden Variable , die den Pseudo-BOM als das ersten 3 Bytes enthalten.

Inkonsistentes Standardcodierungsverhalten in Windows PowerShell :

Leider ist die in Windows PowerShell verwendete Standardzeichencodierung äußerst inkonsistent. die plattformübergreifende PowerShell Core Edition, wie im vorherigen Abschnitt erläutert, hat dies lobenswerterweise beendet.

Hinweis:

  • Das Folgende strebt nicht an, abzudecken alle Standard-Cmdlets .

  • Wenn Sie Cmdlet-Namen googeln, um ihre Hilfethemen zu finden, wird Ihnen standardmäßig die PowerShell Core- Version der Themen angezeigt. Verwenden Sie die Versions-Dropdown-Liste über der Liste der Themen auf der linken Seite, um zu einer Windows PowerShell- Version zu wechseln .

  • Zum jetzigen Zeitpunkt wird in der Dokumentation häufig fälschlicherweise behauptet, dass ASCII die Standardcodierung in Windows PowerShell ist - siehe dieses Problem mit GitHub-Dokumenten .


Cmdlets, die schreiben :

Out-Fileund >/ >>" standardmäßig " Unicode "- UTF-16LE - Dateien erstellen - in denen jedes ASCII-Bereichszeichen (auch) durch 2 Bytes dargestellt wird - was sich erheblich von Set-Content/ unterscheidet Add-Content(siehe nächster Punkt);New-ModuleManifestund Export-CliXmlerstellen Sie auch UTF-16LE-Dateien.

Set-Content(und Add-Contentwenn die Datei noch nicht vorhanden ist / leer ist) verwendet die ANSI-Codierung (die Codierung, die in der ANSI-Legacy-Codepage des aktiven Systemgebietsschemas angegeben ist, die PowerShell aufruftDefault ).

Export-Csv erstellt zwar ASCII-Dateien, wie dokumentiert, siehe jedoch die Hinweise zu -Append .

Export-PSSession Erstellt standardmäßig UTF-8-Dateien mit Stückliste.

New-Item -Type File -Value Derzeit wird UTF-8 ohne Stückliste (!) erstellt.

Das Send-MailMessageHilfethema behauptet auch, dass die ASCII-Codierung die Standardeinstellung ist - ich habe diese Behauptung nicht persönlich überprüft.

Zu Befehlen, die an eine vorhandene Datei angehängt werden:

>>Ich Out-File -Appendmache keinen Versuch, die Codierung des vorhandenen Inhalts einer Datei abzugleichen . Das heißt, sie wenden blind ihre Standardcodierung an, sofern nicht anders angegeben -Encoding, was keine Option ist >>(außer indirekt in PSv5.1 + über $PSDefaultParameterValues, wie oben gezeigt). Kurz gesagt: Sie müssen die Codierung des Inhalts einer vorhandenen Datei kennen und mit derselben Codierung anhängen.

Add-Contentist die lobenswerte Ausnahme: Wenn kein explizites -EncodingArgument vorliegt, erkennt es die vorhandene Codierung und wendet sie automatisch auf den neuen Inhalt an. Danke, js2010 . Beachten Sie, dass dies in Windows PowerShell bedeutet, dass die ANSI-Codierung angewendet wird, wenn der vorhandene Inhalt keine Stückliste enthält, während es sich in PowerShell Core um UTF-8 handelt.

Diese Inkonsistenz zwischen Out-File -Append/ >>und Add-Content, die sich auch auf PowerShell Core auswirkt , wird in diesem GitHub-Problem erläutert .

Export-Csv -Append Teilweise mit der vorhandenen Codierung übereinstimmend: UTF-8 wird blind angehängt, wenn die Codierung der vorhandenen Datei ASCII / UTF-8 / ANSI ist, aber korrekt mit UTF-16LE und UTF-16BE übereinstimmt.
Anders ausgedrückt: In Abwesenheit einer Stückliste wird Export-Csv -AppendUTF-8 angenommen, während Add-ContentANSI angenommen wird.


Cmdlets, die lesen (Codierung ohne Stückliste):

Get-Contentund Import-PowerShellDataFilestandardmäßig ANSI ( Default), was mit übereinstimmt Set-Content.
ANSI ist auch das, was die PowerShell-Engine selbst standardmäßig verwendet, wenn sie Quellcode aus Dateien liest .

Im Gegensatz dazu Import-Csv, Import-CliXmlund Select-Stringdavon ausgehen , UTF-8 in Abwesenheit einer Stückliste.

mklement0
quelle
Können Sie erklären, wie >/ >>wurden effektive Aliase für Out-Filein 5.1?
Maximilian Burszley
@ TheIncorrigible1: Es mag PetSerAl gewesen sein, der mich darauf hingewiesen hat, aber ich erinnere mich nicht, wo und wie. Windows PowerShell ist eine geschlossene Quelle, aber da dieselbe Quasi-Alias-Beziehung auch für PowerShell Core gilt, sollten Sie sie im Quellcode des letzteren finden können.
mklement0
2
Ich bin nicht anderer Meinung, @EliaWeiss, aber es ist speziell Windows PowerShell, und sie haben es schließlich in PowerShell Core richtig gemacht .
mklement0
2
@Marc: VS Code und andere moderne plattformübergreifende Editoren verwenden lobenswerterweise standardmäßig UTF-8, was jedoch bedeutet, dass sie ANSI-codierte Dateien falsch interpretieren. Notepad verwendet Heuristiken, um die Codierung zu erraten . Der Punkt ist, dass es nur eine Vermutung ist , da jede UTF-8-codierte Datei auch eine technisch gültige ANSI-codierte Datei ist (aber nicht umgekehrt). Es wäre großartig, wenn unter Windows standardmäßig UTF-8 verwendet würde, wenn keine Stückliste vorhanden wäre, wie dies bei Unix-ähnlichen Plattformen der Fall ist. Dies ist jedoch nicht der Fall, insbesondere nicht in Windows PowerShell, obwohl dies zum Glück jetzt in PowerShell Core der Fall ist.
mklement0
2
Um Ihren aktuellen Wert zu sehen, geben Sie einfach$PSDefaultParameterValues
Sandburg
2

Um kurz zu sein, verwenden Sie:

write-output "your text" | out-file -append -encoding utf8 "filename"
pbies
quelle