GnuWin32 / sed の Powershell での予期しない動作

GnuWin32 / sed の Powershell での予期しない動作

使っていますGNUWin32 のWindowsコマンドラインツール/パワーシェル

何が見えるか:

 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 によって追加された、データの列間の冗長なスペースを削除します。面白いことに、これは 1 台のコンピューター (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

答え1

それは Unicode です。sed から出力されるものは、PowerShell が Unicode と ASCII を区別するために使用する 2 バイトのプレフィックスのない Unicode です。そのため、PowerShell はそれを ASCII とみなし、\0 バイト (2 バイト Unicode 文字の上位バイト) を残します。これは空白として表示されます。また、PowerShell は内部的に Unicode を扱うため、実際には元のバイトすべてを 2 バイトの Unicode 文字に拡張します。PowerShell に Unicode を受け入れるように強制する方法はありません。考えられる回避策は次のとおりです。

  1. SED への入力として Unicode が使用されていますか? 可能性は低いですが、可能性はあると思います。確認してください。

  2. SED の出力を Unicode インジケーター \uFEFF で開始します。これはおそらく SED ソース コードで抜け落ちているものです。

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

    SEDコマンド内に次のようなコードを追加できます。

    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. sed の出力をファイルに書き込み、Get-Content -Encoding Unicode で読み取ります。ファイルへの切り替えは、次のように cmd.exe 内のコマンドで行う必要があることに注意してください。

    cmd /c "sed ... >file"
    

    >file を PowerShell で処理させると、同じように混乱が生じます。

  4. PowerShell で結果のテキストから \0 文字を削除します。これは、コード 0xA または 0xD を含む Unicode バイトを作成する国際文字ではうまく機能しません。代わりに行分割が行われます。

関連情報