GnuWin32 / sed неожиданное поведение в Powershell

473
mnmnc

Я использую инструменты GnuWin32 в командной строке Windows / Powershell .

Что посмотреть:

 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 

Что я ожидал увидеть:

 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 

Моя цель - избавиться от лишних пробелов между столбцами данных, которые добавляются PowerShell. Самое смешное, что это прекрасно работает на одном компьютере (с Win8.1), но не работает на другом компьютере с Win7.

И это работает для простых примеров:

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

Любая помощь будет высоко ценится.

К вашему сведению - нормальный вывод Get-ChildItems выглядит следующим образом:

 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
Почему бы просто не использовать powershell для всего этого? Какова конечная цель? EBGreen 9 лет назад 0
Конечная цель - использовать такие инструменты gnuWin32, как `cut` и` tr` и `sort`. Это мой предпочтительный способ, так как мне не очень нравится синтаксис Powershell для `Command | Выберите это и это | Format-table`. Также в PowerShell многие вещи, которые передаются через канал, являются объектами, в которых в bash они являются потоками, что для меня гораздо проще манипулировать. mnmnc 9 лет назад 0
Это будет проблема кодирования в среде. Один из способов избежать этого - использовать Out-File, чтобы поместить вывод в файл с любой кодировкой, а затем прочитать файл обратно в sed. EBGreen 9 лет назад 0

1 ответ на вопрос

2
Sergey Babkin

It's the Unicode. The stuff coming out of sed is Unicode without the 2-byte prefix that PowerShell uses to differentiate between Unicode and ASCII. So PowerShell thinks that it's ASCII and leaves the \0 bytes (the upper bytes from 2-byte Unicode characters) in, which display as blanks. And since internally PowerShell deals in Unicode, it actually expands every original byte into a 2-byte Unicode character. The is no way to force PowerShell into accepting Unicode. The possible ways around it are:

  1. Is Unicode coming as input into SED? Unlikely but I think possible. Check that.

  2. Make the output of SED start with the Unicode indicator, \uFEFF. This is probably what got missed in the SED source code:

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

    You can add the code inside the SED command, something like

    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. Write the output of sed into a file and then read with Get-Content -Encoding Unicode. Note that the switch to file must be done in the command inside cmd.exe, like:

    cmd /c "sed ... >file" 

    If you just let >file be handled in PowerShell, it will be messed up in the same way.

  4. Drop the \0 characters from the resulting text in PowerShell. This doesn't work well with the international characters that create the Unicode bytes containing code 0xA or 0xD - you end up with the line splits instead of them.

Отлично, большое спасибо за ваше время и анализ. Сейчас мне намного понятнее. mnmnc 9 лет назад 0