端末出力で単位区切り記号(ASCII 31)が表示されないのはなぜですか?


17

単位区切り文字のASCII文字(ASCII 31、8進数37)は、Vimでとして表示されます^_。しかし、同じファイルを端末に印刷すると、文字は見えなくなります。これにより、行のフィールドがくっついてしまいます。

# In Vim and less:

first field^_second field^_last field

# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field

# print 2nd field with awk 
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field

cat -vを使用して、単位区切りを表示できると仮定します。

cat -v delim.txt
first field^_second field^_last field

しかし、これはかなり面倒です。Bashシェルでstdoutに出力されたときに、単位区切り記号が表示されないのはなぜですか?シェル出力を正しくコピーして貼り付けることもできません。その過程でユニットセパレータが失われます。


すべての文字が印刷可能というわけではありません。単位区切り記号はこれらの1つです。一部のエディターは、編集を可能にする何らかの方法でそれを表示します。あいまいさを減らすために、印刷可能な文字のシーケンスに変換し、場合によっては異なるフォント/色に変換する必要があります。
ctrl-alt-delor

3
31および127未満のASCIIコードは、端末またはデバイスに何かをさせることを意図しているため(制御コードと呼ばれる理由)、何かを表示するのではなく、プロトコル内の何か(EOTやSOHなど)を表します。端末がタイプライターのようなデバイスであり、テレタイプにキャリッジリターンを指示するようなものが物理的に必要であった場合、それは聞き返します。編集者は「^」表記を使用してそれらをレンダリングすることを選択できます。これは、何かを編集しており、制御コードが求めていることを実際に端末で行いたくないからです。
ローレンスC

1
@LawrenceC:コード127は実際に端末に何もさせないことを意図していました。テープをパンチしてミスをした場合、ボタンを押してテープを1スペース分バックアップし、「rub-out」を押してすべてをパンチします8つの穴。読者がすべて穴の開いた文字に出会うと、それは有線で送信されますが、受信者はそれを無視できます。
-supercat

回答:


19

ユニット分離器(USとしても知られている)文字はIS1、であるcntrl文字クラスとではないprint文字クラス。これは、その情報を利用するように設計されたプログラムのために、テキストをグループに編成することを目的とした制御文字です。一般に、印刷できない文字は、異なるプログラムまたは環境で解釈およびレンダリングが異なる可能性があります。

^_Vimのように表示されるのは、Vimがインタラクティブなエディターだからです。正しいバイナリ文字がディスクに書き込まれている限り、印刷可能でない文字を自由にレンダリングできます。

Unixシェルプログラムは、相互に作用してプレーンテキストを渡すように記述されているため、シェルで同じ動作をすることはできません。あなたがcatファイル、端末に書かれているテキストは、ファイル内に実際にあるものでなければなりません。

そのため、文字を解釈するために端末デバイスに任せます。また、一部のターミナルエミュレーターUS、他のエミュレーターと異なるキャラクターをレンダリングます。gnome-terminal(または任意のvteベース端子)、文字が進コードを含むボックスとして表示されます001F。ではxtermまたはrxvt、文字は確かに目に見えないです。


まあ私US完全に目に見えないとは言いません。Ctrl+/(を介して確認<C-v><C-/>)でその文字を端末に挿入すると、その行の予測できない量のテキストが削除されます。私はその動作を完全には理解していませんが、主にいくつかの「逆タブ」効果があり、多くのスペースを挿入する代わりに、いくつかの文字を削除しますが、時にはランダムにテキストを挿入するため、混乱する。
ブレーデンベスト

10

単位区切り記号はASCII範囲の制御文字ですため、視覚的な表現はありません(通常はそうすべきではありません)。

Vimと他のいくつかのエディターはそれらを表示するので、編集することができます。お気づきのように、cat -vそれも表示します。マニュアルページは、それ-vが短い形式であることを示しています--show-nonprinting印刷されない文字を印刷可能な表現に置き換えます。これは、ファイルの元の内容ではないため、出力が実際に別のプログラムである場合に問題を引き起こす可能性があります。

表示される表現は、すでに制御文字であることを示唆しています。先頭にa ^が付いた文字は、Ctrl+の一般的な表記法です。これは、端末でこの文字を生成するキーの組み合わせです。Ctrl+_では、たとえば、vimで単位区切り記号を入力できます。ただし、別のエディターまたはGUIビューアーでは、16進コード、プレースホルダー、またはまったく異なるものが表示される場合があります。

端末は制御文字を印刷しないため、テキストを選択してもコピーされません(改行やタブなどの空白文字はここでは例外であり、制御文字でもあります)。コピー時に通常無視される端末の制御文字の別の例は、カラーコードです。これは、ESC文字の後にテキストを着色するためのコードが続きます。

したがって、端末に文字を表示するには、単位区切り文字を印刷可能な文字に置き換えるプログラムを使用する以外に方法はありません。


3

他の(非常に良い)答えの端に少し、ファイルの内容を表示するときに制御文字のみを変更したい場合は、ユーティリティ(およびbash互換の構文の少し)を使用^_して音訳することをお勧めしtrます。 :

# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'

その制御文字を「拡張された」形式に置き換える必要がある場合は、sed代わりに以下が必要です。

# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g

構文に注意してください$'\cX'。この構文は、対応する制御文字を置き換えるように(bash互換シェル)に通知します。「キャレット表記」を使用した制御文字のエイリアスのリストについては、ウィキペディアを参照してください。その構文が気に入らない場合は、代わりに8 $'\037'$'\x1f'表記または16進表記を使用することをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.