義符是一種特殊的字符常量,具有特定的含義,不同于字符原有的意義。主要用來表示那些用一般字符不便于表示的控制代碼,它的作用是消除緊隨其后的字符的原有含義
轉義符格式:以反斜線"\"開頭,后面緊跟著一個或幾個字符,,介紹幾個常用的
1.\’ 單引號 例如在屏幕上顯示帶單引號的 'How Word'
2.\” 雙引號 例如屏幕輸出 帶雙引號的 "How Word"
3.\ 反斜杠 兩個反斜線代表一個 例如屏幕輸出 D:\
4.\a 警告 發出滴的聲音
5.\b 退格 本來輸入 你好啊\b,張三 結果輸出 你好,張三
6.\n 換行
7.\t 制表符 中間多了幾個空格,并且讓輸出的內容對齊
代碼如下圖所示
我這里將要輸出的內容與轉義字符隔開了,主要是為了方便看清楚,也可以寫在一起
Console.WriteLine("de\tfhi\tjklmn");不影響其轉義
==========@========
假設要輸入一個路徑: d:\asp.net\C#\轉義符.txt
.Console.WriteLine("d:\asp.net\C#\轉義符.txt");//這個書寫起來太麻煩
@的第一個作用就是,當需要輸入特殊字符時,不用再\轉義了,直接在雙引號前面加@
Console.WriteLine(@"d:\asp.net\c#\轉義符.txt");//這個就方便多了
注意:除了對雙引號這個無用外(2),其他幾個(1,3,4,5,6,7)都有用,會原樣輸出
@的第二個作用是可以在輸出語句中按回車鍵換行,如圖所示
慣于使用Linux的人,時常需要在終端命令行工作,默認的黑白界面看的蒼白而單調。實際上我們可以美化它的顯示,之前蟲蟲有很多文章中曾介紹過很多這樣的工具和小APP,大家可以我的參考歷史文章參考學習。除了這些工具外有沒有其他辦法美化命令行呢,還有如何在我們自己的腳本中呈現色彩化的顯示呢?本文蟲蟲就來教你實現這些,包括文字著色,自由的定位移動光標(向上,向下,向左或向右),清屏重顯示(實現動態進度條,ASCII動畫)。這其實都是使用ANSI標準轉義碼編程實現的,今天蟲蟲就給大家來說明ANSI轉義碼的使用方法,最后還使用Python語言實現一個簡單命令行界面。
在*nix體系下數程序與終端交互的方式是通過ANSI轉義碼。這些轉義碼是作為程序可打印的特殊代碼,以便擴展終端的顯示。當然由于兼容性問題,各種終端對ANSI轉義碼支持也有差異,但是基本上在Linux(Windows可能解析有問題)下基本的ANSI轉義代碼還兼容的存在。首先舉個例子"Hello,Chongchong"開始:
最基本的ANSI轉義碼對文本進行渲染的代碼。它允許我們給要打印的文本添加顏色、背景顏色或其他裝飾:
最基本操作是對文本著色。ANSI顏色轉義碼:
紅色:\u001b[31m
重置:\u001b[0m
這個\u001b前綴是大多數ANSI顏色轉義碼的開頭。大多數編程語言都支持用這種語法來表示特殊字符,比如Java,Perl,Python和Javascript等都支持\u001b語法。
例如,這里打印字符串"Hello World",但是紅色:
print("\u001b[31mHello ,chongchong\n")
上面顯示了打印了紅色的Hello chongchong,連提示符都變成紅色的了。事實上,此后再輸入的代碼都將顯示為紅色。這就是Ansi顏色轉義碼渲染的工作方式,設置打印特殊的顏色代碼后,設置就會一直生生效,除非再設置顏色代碼或者用Reset的代碼來恢復到默認顏色。比如我們打印下Reset的代碼:
可以看到提示符號恢復到了回白色。在我們的代碼中如果我們設置過顏色代碼,一定要接著最后用Rest恢復初始環境,對上面的例子我們改造一下:
上面我講了顏色代碼使用和恢復,終端共支持8種(代碼0,30-37)不同的顏色,分別為:
重置:\u001b[0m
黑色:\u001b[30m
紅色:\u001b[31m
綠色:\u001b[32m
黃色:\u001b[33m
藍色:\u001b[34m
洋紅:\u001b[35m
青色:\u001b[36m
白特:\u001b[37m
我們用上面的顏色打印下字母:
大多數終端除了基本的8種顏色外,還支持"明亮"顏色。這些也都有自己的轉義碼,修飾正常的顏色,但在代碼中額外要加一個;1
亮黑: \u001b[30;1m
亮紅: \u001b[31;1m
亮綠: \u001b[32;1m
亮黃: \u001b[33;1m
亮藍: \u001b[34;1m
亮洋紅: \u001b[35;1m
亮青: \u001b[36;1m
亮白: \u001b[37;1m
Reset: \u001b[0m
我們可以打印出這些鮮艷的顏色并看到它們的效果:
可以看到它們確實比基本的8種顏色更亮。黑色A現在足夠亮,可以在黑色背景上成了灰色可見了,白色的H現在比默認的文本顏色更亮。
在16種色的基礎上,有些些終端支持256色的擴展的,265中顏色的轉義碼格式為:
\u001b[38;5;${ID}m
下面我們寫一個程序打印所有者256種顏色,為了顯示方便,我們使用jupyer notebook在瀏覽器上顯示:
import sys
for i in range(0, 16):
for j in range(0, 16):
code=str(i * 16 + j)
sys.stdout.write(u"\u001b[38;5;" + code + "m " + code.ljust(4))
print("\u001b[0m")
其中,也支持用jupyer notebook在瀏覽器上顯示:
代碼中,我們使用sys.stdout.write,這樣就可以在同一行上打印多個顏色,
ANSI轉義碼也支持設置文本背景的顏色。
例如,8種背景顏色對應的代碼為(40-47):
黑色背景: \u001b[40m
紅色背景: \u001b[41m
綠色背景: \u001b[42m
黃色背景: \u001b[43m
藍色背景: \u001b[44m
洋紅背景: \u001b[45m
青色背景: \u001b[46m
黑色背景: \u001b[47m
也支持亮色版本的背景色:
亮黑色背景: \u001b[40;1m
亮紅色背景: \u001b[41;1m
亮綠色背景: \u001b[42;1m
亮黃色背景: \u001b[43;1m
亮藍色背景: \u001b[44;1m
亮洋紅背景: \u001b[45;1m
亮青色背景: \u001b[46;1m
亮白色背景: \u001b[47;1m
Reset的代碼頁一樣都為: \u001b[0m也一樣
我們可以將它們打印出來并看到它們有效:
注意,背景顏色的亮色版不改變背景,而是增加前景文本的亮度,所以顯示效果不是很直觀。
也用一個小腳本展示:
import sys
for i in range(0, 16):
for j in range(0, 16):
code=str(i * 16 + j)
sys.stdout.write("\u001b[48;5;" + code + "m " + code.ljust(4))
print("\u001b[0m")
Jupyter顯示:
除了顏色和背景顏色,ANSI轉義碼還支持一些文本格式修飾符
粗體:\u001b[1m
下劃線:\u001b[4m
反色:\u001b[7m
每一個都可以單獨或者組合使用,或者于顏色符組合使用,看下面的例子:
光標移動的ANSI轉義碼更復雜,它允許我們在終端窗移動光標,或者清除部分窗口。其中最基本的是向上,向下,向左或向右的光標移動:
↑: \u001b[{n}A
↓: \u001b[{n}B
→: \u001b[{n}C
←: \u001b[{n}D
為了演示需要,我們添加一個time.sleep(10),以便觀察顯示效果。
import time
print("Hello I Am Chongchong"); time.sleep(10
光標導航ANSI轉義碼可以利用來做的最簡單的事情就是進度條:
import time, sys
def loading():
print("Loading...")
for i in range(0, 100):
time.sleep(0.1)
sys.stdout.write("\u001b[1000D" + str(i + 1) + "%")
sys.stdout.flush()
print()
loading()
上面我們用ANSI轉義碼來控制終端,創建一個顯示進度百分比,我們對其進行一下美化,比如顯示一個完成進度條:
import time, sys
def loading():
print "Loading..."
for i in range(0, 100):
time.sleep(0.1)
width=(i + 1) / 4
bar="[" + "#" * width + " " * (25 - width) + "]"
sys.stdout.write(u"\u001b[1000D" + bar)
sys.stdout.flush()
loading()
代碼原理:利用循環迭代,刪除整行顯示,然后重新繪制一個更長的顯示,從而實現一個動態ASCII進度條。效果如下:
利用向上和向下光標代碼移動,我們甚至可以一次性繪多個進度條,比如下面代碼我們并行三個進度條顯示:
import time, sys, random
def loading(count):
all_progress=[0] * count
sys.stdout.write("\n" * count)
while any(x < 100 for x in all_progress):
time.sleep(0.01)
unfinished=[(i, v) for (i, v) in enumerate(all_progress) if v < 100]
index, _=random.choice(unfinished)
all_progress[index] +=1
sys.stdout.write("\u001b[1000D")
sys.stdout.write("\u001b[" + str(count) + "A")
for progress in all_progress:
width=progress / 4
print("[" + "#" * width + " " * (25 - width) + "]")
loading()
代碼原理:
為了確保有足夠的空間來繪制進度條,我們通過在函數啟動時寫入"\n" * count來完成的。該代碼會創建一列新行,使終端滾動,確保在終端底部有準確的空白行,以便呈現進度條;使用all_progress數組模擬正在進行的多項操作,并使該數組被隨機填充使用Up ANSI代碼每次移動光標計數行,這樣我們就可以每行打印一個計數進度條。
使用ANSI轉義碼可以做的更有意義事情之一就是實現一個命令行界面。Bash,Python,Ruby都有自己的內置命令行,編輯文本,提交命令,解析執行。上面我們學習了,如何使用ANSI,本部分我們利用這些命轉義碼實現自己的命令行界面。
命令界面最重要的一部分就是用戶接口,負責接受用戶輸入。這可以使用以下代碼完成:
import sys, tty
def command_line():
tty.setraw(sys.stdin)
while True:
char=sys.stdin.read(1)
if ord(char)==3:
break;
print(ord(char))
sys.stdout.write(u"\u001b[1000D")
上面代碼中,我們使用setraw來確保我們的原始字符輸入直接被程序接收,然后讀取并顯示我們的按鍵的ASCII碼,如果按下3(CTRL-C的代碼)。由于我們已打開tty.setraw打印,不會進行光標重置,最后我們執行向左移動\u001b[1000D移動光標到最左。顯示效果如下:
基于上面的基本接口,我們來實現一個原始命令行界面,用來回顯用戶鍵入的內容,我們約定:
當用戶按下可打印字符時,直接打印出來
當用戶按Enter鍵時,打印出用戶輸入,換行輸入。
當用戶按Backspace鍵時,刪除光標所在的一個字符
當用戶按下箭頭鍵時,使用ANSI轉義碼向左或向右移動光標。
首先,讓我們首先實現前兩個功能,代碼如下:
import sys, tty
def command_line():
tty.setraw(sys.stdin)
while True:
input=""
while True:
char=ord(sys.stdin.read(1))
if char==3:
return
elif 32 <=char <=126:
input=input + chr(char)
elif char in {10, 13}:
sys.stdout.write(u"\u001b[1000D")
print("\nechoing..."), input
input=""
sys.stdout.write(u"\u001b[1000D")
sys.stdout.write(input)
sys.stdout.flush()
顯示效果如下:
下一步是讓用戶使用箭頭鍵移動光標。鍵盤上左右箭頭鍵對應于字符碼27 91 68和27 91 67的序列,所以我們可以對輸入代碼檢查并對應移動光標
代碼原理:
通過維護一個索引變量,保留一個單獨的索引,該索引不一定在輸入的末尾,當用戶輸入一個字符時,將其拼接到輸入的正確位置。
檢查char==27,然后檢查接下來的兩個字符來識別左右箭頭鍵,并遞增/遞減光標的索引。
寫入輸入后,手動將光標一直向左移動,并向右移動與光標索引對應的正確字符數。效果如下:
后續根據需要,可以增加Home和End(^和$)功能,只需通過類似方法添加代碼即可,我們不在多贅述。
我們還要實現刪除功能:使用Backspace將會刪除光標前字符,并將光標向左移動一位。為了實現效果我們還得用一個ANSI轉義碼實現各種清屏工作:
清除屏幕:
\u001b[{n}J清除屏幕
n=0從光標清除到屏幕結束,
n=1從光標到屏幕的開頭清除
n=2清除整個屏幕
清除行:
\u001b[{n}K清除當前行
n=0從光標到行尾清除
n=1從光標到行首開始清除
n=2清除整行
下面的代碼:
sys.stdout.write(u"\u001b[0K")
清除光標位置到行末的所有字符。
增加刪除功能后的代碼:
效果如下:
工作原理如下:
光標移動到行的開頭sys.stdout.write(u"\u001b[1000D")
清除行sys.stdout.write(u"\u001b[0K")
當前輸入寫入sys.stdout.write(輸入)
光標移動到正確索引的位置sys.stdout.write(u"\u001b[" + str(index) + "C")
通常,使用這些代碼時候,都會在調用.flush()時生效。
最終我們實現了了一個最小規格的命令行界面,使用sys.stdin.read和sys.stdout.write實現讀寫,用ANSI轉義碼控制終端。
截止目前,我們已經嘗試使用ANSI轉義符顯示顏色,光標導航實現進度條,并實現了一個原始的命令行界面。最后我們給我們的命令行界面增加一個功能,對其中代碼實現語法高亮。
基于我們以后的代碼,實現語法高亮就像在輸入字符串上調用一個syntax_highlight函數一樣簡單,
sys.stdout.write(syntax_highlight(input))
為了演示我將使用一個虛擬語法高亮顯示器來突出顯示尾隨空格。
def syntax_highlight(input):
stripped=input.rstrip()
return stripped + u"\u001b[41m" + " " * (len(input) - len(stripped)) + u"\u001b[0m"
這就是一個最簡單的實例,為了支持更強大的功能,可以利用Pygments的類庫來替換上面syntax_highlight函數,這樣就可以實現任何編程語言的真正的語法高亮。
這種與命令行程序的"豐富"交互是大多數傳統命令行程序和庫所缺乏的。在充分了解ANSI轉義碼的基礎上實現自己的富終端明亮行界面并不像想象的那么難。
位 | bit [b] | 1個數字 |
字節 | byte[B] | 8 b |
千字節 | kb [KB] | 1024 b |
兆字節 | mb[MB] | 1024Kb |
吉字節 | GB | 1024Mb |
太字節 | TB | 124GB |
二進制用8個位置表示:就是256種狀態,就有256種符號
圖示
python - ASCII表
GB2312:80后: 7445個:
GBK:95后
GB18003:00后:27484個字符
Unicode:UTF-8:
chr( ):ASCII碼轉中文
print(chr(20056))乘
ord( ) :中文字符轉ASCII碼
print(ord('乘')):20056
a='a'
print(ord(a)) # 97
print(chr(97)) # a
b='乘'
print(ord(b)) # 20056
print(chr(20056)) # 乘
功能:不希望轉義字符起作用
語法:
r ' 字符中 '
R ' 字符串 '
示例
print(r'12345\b2222')
12345\b2222
注意
最后一個不能是 : \
print(r'hello\nworld\') 這樣就出錯
print('12345\b2222') # 12342222 沒有添加元字符,轉義生效
print(r'12345\b2222') # 12345\b2222 添加過的原字符,轉義無效
功能:將特定字符轉換成特定功能
語法:\ + 字符
\:續行
\n:換行
>\0:空<:空
\t:制表位
\":字符"
\':字符'
\:字符\
\f:換頁
\r:回車,清除前面的數據
\b:退格,刪除前面一個字符
>\0dd:八進制,dd代表字符【\012:換行】<>
\xhh:十六進制,hh代表字符【>\xhh:十六進制,hh代表字符【\0a:換行】<>
# 倒計時功能
import time # 導入時間模塊
# range(10,-1,-1):從10開始到-1,不包括-1,從后向前數。
for i in range(10,-1,-1):
# 前面數據清除,只打印 i 的取值。
print(f'\r開始倒計時:{i}',end=' ')
# 每執行一次,休息1秒。
time.sleep(1)
python 編碼字符與轉義
*請認真填寫需求信息,我們會在24小時內與您取得聯系。