GnuWin32 / sed unerwartetes Verhalten in Powershell

537
mnmnc

Ich verwende GnuWin32- Tools auf der Windows-Befehlszeile / Powershell .

Was ist zu sehen:

 11:15 enlil D:\Users\x> Get-ChildItem .gitconfig | sed "s/ */ /g"   D i r e c t o r y : D : \ U s e r s \ x   M o d e L a s t W r i t e T i m e L e n g t h N a m e - - - - - - - - - - - - - - - - - - - - - - - - - - - - a - - - 6 / 2 3 / 2 0 1 4 4 : 1 1 P M 5 6 . g i t c o n f i g 

Was ich erwartet hatte zu sehen:

 11:15 enlil D:\Users\x> ls .gitconfig | sed "s/ */ /g"   Directory: D:\Users\x   Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 6/23/2014 4:11 PM 56 .gitconfig 

Mein Ziel ist es, redundante Leerzeichen zwischen den Datenspalten zu beseitigen, die von PowerShell hinzugefügt werden. Komisch ist, dass dies auf einem Computer einwandfrei funktioniert (mit Win8.1), auf anderen Computern mit Win7 jedoch nicht.

Und es funktioniert für einfachere Beispiele:

 11:49 enlil D:\Users\x> echo "t a t" | sed "s/ */ /g" t a t 

Jede Hilfe wird sehr geschätzt.

FYI - Die normale Ausgabe von Get-ChildItems sieht folgendermaßen aus:

 11:22 enlil D:\Users\x> ls .gitconfig   Directory: D:\Users\x   Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 6/23/2014 4:11 PM 56 .gitconfig 
0
Warum nicht einfach Powershell für das Ganze verwenden? Was ist das ultimative Ziel? EBGreen vor 9 Jahren 0
Das ultimative Ziel ist es, gnuWin32-Tools wie "cut" und "tr" und "sort" verwenden zu können. Dies ist meine bevorzugte Methode, da ich die Powershell-Syntax für `Command | nicht wirklich mag Wählen Sie dieses und das | aus Format-Tabelle ". Auch in Powershell sind viele Dinge, die durch die Pipe geleitet werden, Objekte, in denen sie in Bash Streams sind - was für mich viel einfacher zu manipulieren ist. mnmnc vor 9 Jahren 0
Es wird ein Codierungsproblem in der Umgebung sein. Eine Möglichkeit, dies zu vermeiden, wäre die Verwendung von Out-File, um die Ausgabe mit einer beliebigen Kodierung in eine Datei zu packen und die Datei anschließend wieder in sed zu lesen. EBGreen vor 9 Jahren 0

1 Antwort auf die Frage

2
Sergey Babkin

Es ist der Unicode. Das Ergebnis von sed ist Unicode ohne das 2-Byte-Präfix, mit dem PowerShell zwischen Unicode und ASCII unterscheidet. PowerShell denkt also, dass es sich um ASCII handelt, und belässt die Bytes (die oberen Bytes von 2-Byte-Unicode-Zeichen), die als Leerzeichen angezeigt werden. Da PowerShell intern mit Unicode arbeitet, erweitert es tatsächlich jedes ursprüngliche Byte in ein 2-Byte-Unicode-Zeichen. Dies ist keine Möglichkeit, PowerShell zu zwingen, Unicode zu akzeptieren. Die möglichen Wege sind:

  1. Kommt Unicode als Eingabe in SED? Unwahrscheinlich, aber ich denke möglich. Prüfe das.

  2. Lassen Sie die Ausgabe von SED mit dem Unicode-Kennzeichen \ uFEFF beginnen. Dies wurde wahrscheinlich im SED-Quellcode übersehen:

    _setmode(_fileno(stdout), _O_WTEXT); // probably present and makes it send Unicode wprintf(L"\uFEFF"); // probably missing 

    Sie können den Code innerhalb des SED-Befehls hinzufügen

    sed "1s/^/\xFF\xFE/;..." # won't work if SED produces Unicode but would work it SED passes Unicode through from its input sed "1s/^/\uFEFF/;..." # use if SED produces Unicode itself, hopefully SED supports \u 
  3. Schreibe die Ausgabe von sed in eine Datei und lese dann mit Get-Content -Encoding Unicode. Beachten Sie, dass die Umstellung auf Datei in dem Befehl in cmd.exe erfolgen muss, z. B .:

    cmd /c "sed ... >file" 

    Wenn Sie> Datei einfach in PowerShell behandeln lassen, wird dies auf dieselbe Weise durcheinander gebracht.

  4. Löschen Sie die \ 0-Zeichen aus dem resultierenden Text in PowerShell. Dies funktioniert nicht gut mit den internationalen Zeichen, aus denen die Unicode-Bytes bestehen, die den Code 0xA oder 0xD enthalten. Am Ende erhalten Sie die Zeilenaufteilungen statt.

Großartig, vielen Dank für Ihre Zeit und Analyse. Es ist jetzt viel klarer für mich. mnmnc vor 9 Jahren 0