このコマンドは、Linuxではファイルを0xff
で埋めます。
dd if=/dev/zero ibs=1k count=100 | tr "\000" "\377" >paddedFile.bin
OSXで実行すると、結果が異なります。
$ dd if=/dev/zero ibs=1k count=100 | tr "\000" "\377" >paddedFile.bin
100+0 records in
200+0 records out
102400 bytes transferred in 0.000781 secs (131104008 bytes/sec)
$ hexdump -C paddedFile.bin
00000000 c3 bf c3 bf c3 bf c3 bf c3 bf c3 bf c3 bf c3 bf
|................|
*
00032000
何が起きてる?
これはすべて、実行時にターミナルセッションで設定されたLANG
またはLC_ALL
の値に依存します tr
。 LinuxではそれらがC
に設定されていますが、macOSではen_US.UTF-8
のようなものに設定されています。もちろん、en_US
はen_UK
(英国英語)などの他のローカル言語である可能性がありますが、ポイントは、プレーンASCII viaC
がこれを引き起こしているのではなく[something].UTF-8
設定です。
MacOSの tr
は、純粋なASCII 0xff
の代わりに、c3bf
を0xff
に相当するUTF8に変換しているようです。これについては this Appleコミュニティサポートスレッドはこちら :
Linuxは、MacのようにターミナルでUnicodeを処理しません。 「LANG」環境変数を「C」に設定すると(おそらくLinux上にあるため)、機能します。それ以外の場合、これらの上位ビットはすべてUnicode文字として解釈されます。
そして、そのLANG
ヒントを使用すると機能します!次のようにしてください。私が今macOS10.13.6(High Sierra)で個人的にテストしました。
まず、既存のLANG
値が次のようになっていることに注意してください。
echo $LANG
私が見る出力は次のとおりです。
en_US.UTF-8
次に、LANG
値を次のようにC
に設定します。
LANG=C
そして、そのコマンドを再度実行します。
dd if=/dev/zero ibs=1k count=100 | tr "\000" "\377" >paddedFile.bin
これで、hexdump
値は次のようになります。
hexdump -C paddedFile.bin
00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00019000
LANG
値をリセットするには、そのターミナルセッションを閉じるか、次のコマンドを実行します。
LANG=en_US.UTF-8
または、コメントで指摘されているように、次のようにLANG
を呼び出す前に、コマンドラインオプションでtr
値を直接設定できます。
dd if=/dev/zero ibs=1k count=100 | LANG=C tr "\000" "\377" >paddedFile.bin
また、LANG
はLC_ALL
から派生しているため、LANG
の代わりにLC_ALL
を使用することもできます。
dd if=/dev/zero ibs=1k count=100 | LC_ALL=C tr "\000" "\377" >paddedFile.bin
問題は、Linux上にあるGNU tr
は、実際にはマルチバイト文字の概念を持っておらず、代わりに一度にバイト単位で機能することです。
tr
man page およびオンラインドキュメントでは文字について説明していますが、これは少し単純化したものです。ソースコードパッケージのTODO
ファイルはこのアイテムに言及しています( coreutils 8. から選択):
Wc、tr、fmtなどのツール(ほとんどのtextutils)をマルチバイト対応に適合させます。問題は、ロジックの重要なブロックの重複を避けたいということですが、シングルバイトモードで動作する場合は最小限の(できれば「いいえ」)コストしか発生させたくないのです。
Linuxシステムでは、UTF-8ロケール(en_US.UTF-8
)を使用している場合でも、GNU tr
はä
を2つの「文字」として置き換えます(ä
のUTF-8表現は2バイトです)。
linux$ echo 'ä' | tr 'ä' 'x'
xx
同様に、ä
とö
を混在させると、UTF-8表現が共通のバイトを共有するため、面白い結果が得られます。
linux$ echo 'ö' | tr ä x
x�
またはその逆(x
はここでは適用されません):
linux$ echo ab | tr ab äx
ä
そしてあなたの場合、GNU tr
は\377
を生のバイト値として取ります。
Macのtr
は異なり、マルチバイト文字の概念を認識しており、それに応じて動作します。
mac$ echo 'ä' | tr ä x
x
mac$ echo ab | tr ab äx
äx
数値0377(U + 00ff)の文字のUTF-8表現は2バイトc3 bf
であるため、これが得られます。
tr
をバイトごとに機能させる簡単な方法は、UTF-8ロケールではなくCロケールを使用することです。これは再び面白い振る舞いをします:
$ echo 'ä' | LC_ALL=C tr 'ä' 'x'
xx
そしてあなたの場合、あなたは使用することができます:
... | LC_ALL=C tr "\000" "\377"
または、Perlのようなものを使用してそれらの\xff
バイトを生成することもできます。
Perl -e 'printf "\377" x 1000 for 1..100'