参考文献

参考文献

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 16 進数では 5F)、\b は Ctrl-H または ASCII 16 進数では 08 です。これは何でしょうか。わかりにくいターミナル コードがたくさんあることは知っていますが、\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-V Ctrl-H を押すことで作成されます。しかし、どちらも cal と同じ反転ビデオ出力を生成しません。私も、これを行うために小さな C プログラムを書いてみました。また、echo -e でも試しました。興味深いのは、端末でビデオが反転しないのに、less -R からの出力をパイプすると、色が黄色に変わり、下線が引かれることです。他の端末では、下線だけが引かれるように試しました。まるで重ね打ちのように見えますが、_ 以外の文字を使用すると機能しないので、_\b は単一のコード シーケンスであると考えられます。では、その文字のビデオはどのようにして反転されるのでしょうか。

これについて何か知見はありますか?

man ページには、cal の出力は元の Unix cal コマンドとビット単位で互換性のあるバージョンになるはずだと書かれています。したがって、これは古いコードだとしか思えません。

答え1

まるで過剰攻撃のようだ

まさにその通りです。80 列のコンソールにタブストップが 11 個あるのはなぜですか?、Unix 端末に関しては、機械式タイプライターの動作を思い浮かべると分かりやすいでしょう。この場合、_ 文字の前のシーケンス BS (バックスペース文字) は、その文字に下線を引くことを示すために使用される慣例です。一部の端末では、テキストに下線を引くときにこのシーケンスが使われていたからです。別の制御シーケンスは、_文字の後の BS です。もちろん、オリジナルの端末では、どの文字がどの文字に重なっても問題ありませんでした。現代のビデオ端末では、最後に書き込まれた文字が「勝ち」、前のデータが消去されます。したがって、_ BS <キャラクター>順番が優先されます。

このプログラムであるFreeBSDncalには、ハイライト表示に関して 2 つの動作モードがあります。

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

BS シーケンスを端末に送ることでこれを再現することはできません_。ただし、(もちろん) 端末が、このように下線を引く端末の 1 つである場合は除きます。これは端末エミュレーターには当てはまりませんし、ここで使用している端末や端末エミュレーターにもほぼ間違いなく当てはまりません。

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

他の端末で試してみたところ、下線が引かれるだけでした。

ncal皮肉なことに、プログラムを通しての非端末モード出力をフィルタリングすることは、端末制御シーケンス自体を書き込むulよりもわずかに優れていますncal。一方、ncalは端末の目立つモードでは、ul端末の実際の下線BS シーケンスを変換するときに、強調モード (ある場合) を使用します_。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\b 3 _\b4. \b\b\b45 6\n" | ul
  • /usr/bin/printf "1 2 ______\b\b\b\b\b\b\b 3 _\b4. \b\b\b45 6\n" | 以下

古き良き時代に戻る

残念なことに、これらはまだ「古き良き時代」です。現在ではほとんど使用されていないと騙されないでください。

マニュアルには記載されていないが、のソースコードでは、ulテレタイプモデル37の制御シーケンス処理を実装しようとしていることが指摘されている。なぜなら、「それがnroff出力される」からだ。端末が色、太字、斜体などの派手な機能を獲得してからずっと後に書かれた、オリジナルのUnixプログラムのGNU代替品はnroff、次のようなものを生成することができる。ECMA-48色、太字、斜体の制御シーケンス。実際にそうする通常の場合

nroffおよびその GNU 代替品は、端末に表示するためのマニュアル ページの書式設定に使用されます。悲しいことに、皮肉なことに、作成されてから約 10 年後、人々は GNU ツールを妨害し、1976 年の「新しい」ECMA-48 制御シーケンスではなく、1968 年の古い Teletype Model 37 シーケンスを生成するようにしました (sic!)。彼らは、デフォルトの動作を変更するオプションを指定してman呼び出しgroff、追加の ditroff 出力を強制する文書化されていないファイルを追加しました。

端末でマニュアル ページを読むたびに、マニュアル システムが実行され、groffマニュアルのソース テキストが、古い Teletype Model 37 制御シーケンスを使用して出力文字ストリームに変換され、端末の制御シーケンスに変換されますlessmore

参考文献

  • ジョナサン・デ・ボイン・ポラード(2016年)。  nosh ユーザー空間仮想端末のマニュアルページの斜体と色アーカイブ版現行版)。nosh パッケージ。
  • ジョナサン・デ・ボイン・ポラード(2017年)。  改良されたマニュアルページulアーカイブ版現行版)。提案。

答え2

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

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

関連情報