web-dev-qa-db-ja.com

viには表示されますが、catには表示されない文字。

ファイル内の各文字の間に^@文字を含む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で読み取り可能になり、grepcatから結果を返します。

[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マシンから自動生成されたファイルです。 ^@はどのような状況でファイルに侵入しますか。

4
Sree

ファイルの形式はおそらくリトルエンディアンの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に音訳することをお勧めする方法がわかりませんが、使用したことはありません。

5
Bruce Ediger
  1. はい、grep sw ^@文字。 catは端末に文字を出力していますが、表示されない文字です。キャラクターが見えないからといって、そこにいないわけではありません。

  2. どちらが必要なものに最適かによって、選択/好み。ただし、viにはファイルを変更する可能性があることに注意してください。

  3. ^@は自然な性格ではありません。 Windowsプログラムは、これらの文字を積極的に配置しています。その理由を知るには、プログラマーに尋ねる必要があります。ほとんどの場合、Windowsプログラムは文字が16ビット幅であると想定しており、Unixマシンは文字が8ビット幅であると想定しています。

4
hymie