進一步閱讀

進一步閱讀

當您在 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 十六進位中的 5F),\b 是 Ctrl-H 或 ASCII 十六進位中的 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 是單一代碼序列。那麼該角色的影片如何反轉呢?

對此有何見解?

手冊頁說 cal 的輸出應該是與原始 Unix cal 指令有點相容的版本。所以我只能假設這是一些古老的程式碼。

答案1

這幾乎看起來有點過分了

正是如此。正如所討論的為什麼 80 列的控制台上有 11 個製表符?,當涉及 Unix 終端時,它有助於思考機械打字機的操作。在這種情況下,字元之前的序列_ BS(退格字元)是一種約定,用於指示該字元的下劃線,因為在某些終端上,這就是文字下劃線的方式。另一種控制序列是_字元後的 BS。當然,在最初的終端上,什麼超越什麼並不重要。在現代視訊終端上,最後寫入的字元“獲勝”,從而擦除先前的資料。因此,_ BS <字元>順序優先。

FreeBSD ncal,也就是這個程序,在突出顯示方面有兩種操作模式。

  • 如果其輸出是終端,它將在 termcap 資料庫中尋找當前終端類型的sose序列,並在突出顯示的文字的兩側發出這些序列。 (實際上,執行此操作的程式碼中有一個錯誤,與堆疊上的緩衝區超出範圍及其內容稍後使用有關,似乎沒有人發現這一點。)
  • 如果它的輸出不是終端,它會發出文本,其中每個要突出顯示的字元前面都有_BS 序列。

你不能透過向終端發出 BS 序列來複製這一點_,除非(當然)你的終端是這樣強調內容的終端之一。終端模擬器不是這種情況,幾乎可以肯定,您在這裡使用的任何終端或終端模擬器都不是這種情況。

但是,您可以篩選透過程式使用此約定的文本,ul該程式識別此約定以及其他幾個類似打字機的約定,並將它們轉換為終端實際的控制序列,並在 termcap 資料庫中查找它們。您也可以printf透過過濾命令的輸出ul

在其他終端上我嘗試過它只是強調它。

ncal諷刺的是,透過程式過濾非終端模式輸出ul實際上比讓ncal編寫終端控制序列本身稍好一些。而ncal使用終端的脫穎而出模式,ul將嘗試使用終端的實際強調轉換 BS 序列時的模式(如果有)_。如 termcap 手冊所解釋的,突出模式可以是任何適合終端的模式(包括粗體、反向視訊或顏色),且不一定是底線。在您的一個終端上,它顯然是下劃線和顏色變化的組合。

此外,ul還可以處理沒有下劃線開始/結束序列但有下劃線最後一個字元序列的終端。諷刺的是,ul如果您的終端能夠應對真的是_一個在每個字元後面加上 BS 來強調的,而ncal無法應對。

當然,ul沒有ncal緩衝區處理錯誤。 ☺

如果我將輸出通過管道傳輸到less -R,它會將其顏色更改為黃色並為其添加下劃線。

正如您所發現的,該less程式理解_BS 序列並按照ul程式的方式處理它們。並不完全一樣。 ul可以處理涉及多個 BS 字元的序列_,也可以處理類似的粗體字元序列。 less不能。對比一下您從這兩者中看到的情況:

  • /usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4.\b\b\b45 6\n" |烏爾
  • /usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4.\b\b\b45 6\n" |較少的

回到過去的美好時光

可悲的是,這些仍然是「美好的舊時光」。不要讓人們欺騙您,讓您相信現在很少使用此功能。

它不在手冊中,但原始程式碼指出ul它正在嘗試實作 Teletype Model 37 的控制序列處理,因為「這就是輸出nroff」。原始 Unix 程式的 GNU 替代品nroff是在終端獲得顏色、粗體和斜體等奇特功能很久之後編寫的,能夠生成ECMA-48顏色、粗體和斜體的控制序列。它實際上是這樣做的在正常情況下

nroff及其 GNU 替代品用於格式化手冊頁以在終端機上顯示。可悲且諷刺的是,從它編寫大約10 年後開始,人們開始對GNU 工具進行修改,使其生成1968 年的舊Teletype Model 37 序列,而不是1976 年的“新”ECMA-48 控制序列(原文如此!他們使用修改其預設行為的選項進行man調用groff,並添加強制額外 ditroff 輸出的未記錄檔案。

每次您在終端機上閱讀手冊頁時,手冊系統都會運行groff,該系統會盡職盡責地將手冊來源文字轉換為使用這些舊的 Teletype Model 37 控制序列的輸出字元流,這些控制序列lessmore正在轉換為終端的控制序列。

進一步閱讀

  • 喬納森·德博因·波拉德 (2016)。  nosh 使用者空間虛擬終端機上手冊頁中的斜體和顏色存檔版本,目前版本)。小吃包。
  • 喬納森·德博因·波拉德 (2017)。  改進的手冊頁ul存檔版本,目前版本)。提案。

答案2

Ctrl-H是退格鍵,它將遊標向左移動一步。在過去的好日子裡,發送下劃線、退格鍵和其他一些字元是在硬拷貝(“紙質”)終端上給某些內容加下劃線的方法。這用於在 的輸出中突出顯示當天cal

我的cal程式在運行時konsole不會輸出此序列。如果我運行script -c cal並檢查生成的typescript文件,我可以看到 cal 程式使用轉義序列<esc>[7m切換到反轉模式影片。

相關內容