web-dev-qa-db-ja.com

'cal'がハイライトに奇妙な08 / ^ H / \ bターミナルコードを使用するのはなぜですか?それはどのように機能しますか?

Linuxでcalを実行すると、今月の出力でビデオが反転し、当日のハイライトが表示されます。その出力をhexdump-cに送信すると、いくつかの興味深い結果が得られます。

0000000               N   o   v   e   m   b   e   r       2   0   1   6
0000010                          \n   S   u       M   o       T   u    
0000020   W   e       T   h       F   r       S   a          \n        
0000030                       1           2       _  \b       _  \b   3
0000040           4           5          \n       6           7        
0000050   8           9       1   0       1   1       1   2          \n
0000060   1   3       1   4       1   5       1   6       1   7       1
0000070   8       1   9          \n   2   0       2   1       2   2    
0000080   2   3       2   4       2   5       2   6          \n   2   7
0000090       2   8       2   9       3   0                            
00000a0                  \n                                            
00000b0                                              \n                
00000bc

ご覧のとおり、今日強調表示されている「3」の前に_\b _\bの非表示のシーケンスが印刷されています。 _はアンダースコア(ascii hexでは5F)であり、\ bはCtrl-Hまたは08in ASCII hexです。これは何ですか?あいまいな端末コードがたくさんあることは知っていますが、期待しています\ e [7mのようなより標準的なものを使用します。さらに奇妙なのは、次のコマンドのような標準のprintf関数を使用して同じ文字を出力しても、calの同じ動作を再現できないことです。

/usr/bin/printf "1 2 _\b _\b3 4 5\n"
/usr/bin/printf "1 2 _^H _^H3 4 5\n"

ここで、^ Hは、Ctrl-VCtrl-Hを押して作成します。しかし、これらはどちらも、calと同じ逆ビデオ出力を生成しません。私もそれをするために小さなCプログラムを書いてみました。 echo-eも試してみました。興味深いのは、ターミナルでビデオを反転させない一方で、より少ない-Rから出力をパイプすると、色が黄色に変わり、下線が引かれることです。他の端末では、下線を引いてみました。重ね打ちのように見えますが、_以外の文字を使用すると機能しないため、_\bは単一のコードシーケンスであると思われます。そして、そのキャラクターのビデオはどのように反転されますか?

これについて何か洞察はありますか?

マニュアルページには、calの出力は、元のUnixcalコマンドとビット互換バージョンのビットであると想定されていると書かれています。だから私はこれがいくつかの古代のコードであると推測することしかできません。

3
deltaray

Ctrl-Hはバックスペースで、カーソルを1ステップ左に移動します。古き良き時代に、アンダースコア、バックスペース、およびその他の文字を送信することは、ハードコピー(「紙」)端末で何かに下線を引く方法でした。これは、calの出力で当日を強調するために使用されました。

私のcalプログラムは、konsoleで実行すると、このシーケンスを出力しません。 script -c calを実行して結果のTypeScriptファイルを調べると、calプログラムがエスケープシーケンス<esc>[7mを使用して逆モードビデオに切り替えていることがわかります。

3
Johan Myréen

重ね打ちのようです

それがまさにそれです。 https://superuser.com/a/711019/38062 のように、Unix端末に関しては機械式タイプライターの動作を考えると役立ちます。この場合、文字の前のシーケンス_ BS(バックスペース文字)は、その文字の下線を示すために使用される規則です。一部の端末では、テキストに下線を引く方法があるためです。代替の制御シーケンスは、文字の後のBS _です。もちろん、元の端末では、何が何を超えたかは問題ではありませんでした。

このプログラムが何であるかであるFreeBSDncalには、強調表示に関して2つの操作モードがあります。

  • 出力が端末の場合、termcapデータベースで現在の端末タイプのsoおよびseシーケンスを検索し、強調表示されたテキストのいずれかの側に出力します。 (実際には、これを行うコードにバグがあり、スタック上のバ​​ッファがスコープ外になり、その内容が後で使用されるため、誰も発見していないようです。)
  • 出力が端末でない場合は、強調表示される各文字の前に_BSシーケンスが付いたテキストを出力します。

_ BSシーケンスを端末に発行してこれを複製することはできません。ただし、(もちろん)端末が端末の1つであり、これが下線を引く方法である場合を除きます。これはターミナルエミュレーターには当てはまりません。また、ここで使用しているターミナルやターミナルエミュレーターにも当てはまります。

ただし、filterこの規則を使用するテキストは、ulプログラムを介して、これと他のいくつかのタイプライターのような規則を認識し、端末の制御シーケンスが実際にあるものに変換して、で検索することができます。 termcapデータベース。 printfコマンドの出力をulでフィルタリングすることもできます。

他の端末では、下線を引いてみました。

皮肉なことに、ncalプログラムを介してulの非端末モード出力をフィルタリングすることは、実際にはncalに端末制御シーケンス自体を書き込ませるよりもわずかに優れています。 ncalは端末のstandoutモードを使用しますが、ulは、_ BSシーケンスを変換するときに、端末の実際のnderlineモード(ある場合)を使用しようとします。 termcapのマニュアルで説明されているように、目立つモードは端末に適したもの(太字、反転ビデオ、色など)であり、必ずしも下線が引かれているわけではありません。端子の1つでは、明らかに下線と色の変更の組み合わせです。

さらに、ulは、開始/終了シーケンスに下線が付いていないが、最後の文字シーケンスに下線が付いている端末にも対応します。皮肉なことに、ulは端末が本当に各文字の後にBS_を付けることで下線を引く場合に対応しますが、ncalは対応しません。

そしてもちろん、ulにはncalのバッファ処理のバグはありません。 ☺

出力をless -Rにパイプすると、色が黄色に変わり、下線が引かれます。

お気づきのとおり、lessプログラムは_ BSシーケンスを理解し、ulプログラムと同じように処理します。それは完全に同じではありません。 ulは、複数の_およびBS文字を含むシーケンスを処理でき、太字の同様のシーケンスも処理できます。 lessはできません。これら2つからわかるものを比較してください。

  • / usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4。\ b\b\b45 6\n" | ul
  • / usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4。\ b\b\b45 6\n" | less

古き良き時代に戻って

悲しいことに、これらはまだ「古き良き時代」です。これが今日ではめったに使用されないと人々に信じ込ませないでください。

マニュアルにはありませんが、ulのソースコードは、「それがnroffの出力である」ため、テレタイプモデル37の制御シーケンス処理を実装しようとしていることを示しています。 GNU元のUnixnroffプログラムの代わりに、端末が色、太字、斜体などの高度な機能を取得してからずっと後に作成され、色、太字、および斜体のECMA-48制御シーケンスを生成できます。イタリック。実際にはそうします通常の場合

nroffとそのGNU置換は、端末に表示するためのマニュアルページのフォーマットに使用されます。悲しいことに、皮肉なことに、それが書かれてから約10年後に、人々はGNUツールにより、1976年の「新しい」ECMA-48制御シーケンスの代わりに1968年の古いテレタイプモデル37シーケンスが生成されました(原文のまま)。デフォルトの動作を変更するオプションを使用して、mangroffを呼び出させました。そして、余分なditroff出力を強制する文書化されていないファイルを追加しました。

端末で手動ページを読むたびに、手動システムはgroffを実行しています。これは、手動のソーステキストをこれらの古いTeletype Model 37制御シーケンスを使用して出力文字ストリームに忠実に変換し、lessまたはmoreは端末の制御に変換します。シーケンス。

参考文献

2
JdeBP