ファイル内の各文字の間に^@
文字を含む300行のファイルがあります。
(セキュリティ上の理由により、内容全体を投稿することはできませんので、最初の行のみを貼り付けています)
[mercury@app01 ftp_logs]$ cat cl.txt
2015-01-22 03:00:01; local;
ここで、ファイルをvi
すると、次のような内容が表示されます。
2^@0^@1^@5^@-^@0^@1^@-^@2^@2^@ ^@0^@3^@:^@0^@0^@:^@0^@1^@;^@ ^@l^@o^@c^@a^@l^@;^@
cat
は^@
文字を表示していなかったので、当然、特定の文字列のgrepはcat
で機能すると思いましたが、驚くべきことに、そうではありませんでした。
[mercury@app01 ftp_logs]$ cat cl.txt
2015-01-22 03:00:01; local;
[mercury@app01 ftp_logs]$ cat cl.txt | grep local
[mercury@app01 ftp_logs]$
Nullバイトをsed
に置き換えた後、ファイルはvi
で読み取り可能になり、grep
はcat
から結果を返します。
[mercury@app01 ftp_logs]$ sed -i 's/\x0//g' cl.txt
[mercury@app01 ftp_logs]$ cat cl.txt | grep local
2015-01-22 03:00:01; local;
[mercury@app01 ftp_logs]
質問:
1)nullバイトが表示されなかったのに、nullバイトを置き換える前にgrep
が機能しなかったのはなぜですか。ターミナルに表示されていなくても、grep
が^@
文字を見たということですか?
2)これは、vi
が物を隠すのに適しているように見えるので、cat -v
またはcat
を使用して本番サーバー上のファイルを読み取ることが推奨されるかどうか疑問に思います。
3)問題のファイルは、Windowsマシンから自動生成されたファイルです。 ^@
はどのような状況でファイルに侵入しますか。
ファイルの形式はおそらくリトルエンディアンのUTF-16です。 Windows上の一部のアプリはデフォルトでこれに設定されているようで、多くの移植性の問題を引き起こします。
vi
は、ASCII-Nul(数値的にゼロ)値のバイトを '^ @'(control-At)として表します。 control-shift- @コードを使用して、実際にはvim
にゼロ値のバイトを入力できます。
grep
は、ファイルをUTF-16として解釈するのではなく、ACII-Nulバイトを確認し、「2」や「0」などのUnicodeコードポイントを確認する必要があります。 GNU grep
のマニュアルページにUTFを処理するためのオプションがありません-何でも。
cat
はASCII-Nulbtyesを表示しません。問題の端末エミュレーターはそれらを表示しますが、使用している端末エミュレーターはそれらを無視します。 cat cl.txt | od -x
以上のcat cl.txt | xxd
を使用すると、cat
の出力にASCII-Nulバイトが表示されます。ファイルの最初の2バイトとして「ffef」や「efff」のようなものが表示された場合、それらはすべての常識に反してMicrosoftによって公布された「バイトオーダーマーク」です。
UTF-16をASCIIまたはUTF-8、iconv
に音訳することをお勧めする方法がわかりませんが、使用したことはありません。
はい、grep
sw ^@
文字。 cat
は端末に文字を出力していますが、表示されない文字です。キャラクターが見えないからといって、そこにいないわけではありません。
どちらが必要なものに最適かによって、選択/好み。ただし、vi
にはファイルを変更する可能性があることに注意してください。
^@
は自然な性格ではありません。 Windowsプログラムは、これらの文字を積極的に配置しています。その理由を知るには、プログラマーに尋ねる必要があります。ほとんどの場合、Windowsプログラムは文字が16ビット幅であると想定しており、Unixマシンは文字が8ビット幅であると想定しています。