web-dev-qa-db-ja.com

端末出力で単位セパレータ(ASCII 31)が表示されないのはなぜですか?

ユニットセパレータ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に出力すると、単位セパレーターが表示されないのはなぜですか?シェルの出力をコピーして貼り付けることもできません。その過程でユニットセパレーターは失われます。

18
dan

単位区切り文字(US)はIS1とも呼ばれ、cntrl文字クラスにあり、ではありませんprint文字クラス。これは、テキストをグループに編成するための制御文字です。その情報を利用するように設計されたプログラムの場合。一般に、印刷不可能な文字は、プログラムや環境によって解釈やレンダリングが異なる可能性があります。

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

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

したがって、文字を解釈するのは端末デバイスに任せます。また、一部の端末エミュレーターdoは、US文字を他のエミュレーターとは異なる方法でレンダリングすることがわかりました。 gnome-terminal(またはvteベースの端末)では、文字は16進コード001Fを含むボックスとしてレンダリングされます。 xtermまたはrxvtでは、文字は実際には見えません。

20
Mike Miller

単位区切り記号は、ASCII 制御文字 の範囲内にあるため、視覚的に表示されません(または通常は表示されません)。

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

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

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

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

10
crater2150

表示するときに制御文字^_のみ変更したい場合は、他の(非常に良い)回答のマージンに少しファイルの内容は、trユーティリティを使用してtransliterateする必要があります(およびbash互換の構文の少し):

# 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'または16進数の$'\x1f'表記を使用することをお勧めします。

3
Sylvain Leroux