【Python】linux系統more基本命令python原始碼分享

程式設計師啟航發表於2019-06-26

此python原始碼是linux系統more基本命令的實現。
實現linux中more的基本功能,當more後加一個檔名引數時候,分屏顯示按空格換頁,按回車換行',在左下角顯示百分比;
以處理管道引數的輸入,處理選項+num:從指定行開始顯示,+/string :查詢字串,從指定字串之後開始顯示

執行環境:安裝有PYTHON的linux系統

呼叫示例:
more.py [+num ] [+/pattern] filename
command|./more.py [+num ] [+/pattern]
more.p --help 輸出幫助資訊
num 是 要從第幾行開始顯示,pattern是要在檔案中查詢的字串

學習python過程中有不懂的可以加入我的python零基礎系統學習交流秋秋qun:前面是784,中間758,後面是214,與你分享Python企業當下人才需求及怎麼從零基礎學習Python,和學習什麼內容。相關學習視訊資料、開發工具都有分享!

`#!/usr/bin/env python`
`# -*- coding:utf-8-*-`
`#檔名字:more.py`
`import` `os`
`import` `sys`
`import` `curses` `#用於獲取終端的尺寸`
`import` `re` `#用於字元匹配`
`import` `signal` `#用於處理ctrl+c中斷`
`import` `fcntl` `# 處理顯示過程中螢幕的變化`
`import` `termios` `#獲取終端資訊`
`import` `struct`
`page_len` `=` `0`   `#滿屏時可以顯示的最大行數`
`line_len` `=` `0`   `#滿屏時每行可以顯示的最大位元組數`
`sig_up` `=` `0`    `#中斷訊號標誌`
`winsz_chg` `=` `0`   `#視窗大小改變標誌`
`def` `win_sz_chg(signum, frame):`
`'''  函式功能:本函式是螢幕變化訊號的處理函式'''`
`global` `page_len, line_len, winsz_chg`
`winsz_chg` `=` `1`
`signal.signal(signal.SIGWINCH, signal.SIG_IGN)`
`s` `=` `struct.pack(``"HHHH"``,` `0``,` `0``,` `0``,` `0``) `
`a` `=` `struct.unpack(``'hhhh'``, fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))`
`#獲取當前視窗的大小`
`page_len` `=` `int``(a[``0``])` `-` `1`  `#留一行顯示進度`
`line_len` `=` `int``(a[``1``])`
`signal.signal(signal.SIGWINCH, win_sz_chg)` `#不呼叫會導致只能檢測一次螢幕變化`
`signal.signal(signal.SIGWINCH, win_sz_chg)` `#接收處理視窗改變訊號`
`def` `term_do_exit(signum, frame):`
`'''  函式功能:鍵盤中斷訊號的響應函式'''`
`global` `sig_up`
`sig_up` `=` `1`           `#將鍵盤中斷標誌置1`
`os.system(``"stty -F /dev/tty echo"``)` `#恢復終端輸出回車有效狀態`
`os.system(``"stty -F /dev/tty -cbreak"``)``#重新設著螢幕為輸入字元回顯狀態`
`return`
`signal.signal(signal.SIGINT, term_do_exit)` `#接收並處理鍵盤中斷訊號`
`def` `usage():`
`'''顯示指令碼的各引數的含義和呼叫格式'''`
`print` `"-----------------usage-----------------"`
`print` `"1./more.py [+num] [+/pattern] filename"`
`print` `"2 command | ./more.py"`
`print` `"num: Start at line number num. "`
`print` `"pattern:Start at line number num."`
`print` `"space: next page"`
`print` `"q :do_exit the program"`
`print` `"enter:next line"`
`print``"----------------------------------------"`
`sys.exit()`
`def` `do_exit():`
`'''用於系統退出 '''`
`os.system(``"stty -F /dev/tty echo"``)` `#恢復終端輸出回車有效狀態`
`os.system(``"stty -F /dev/tty -cbreak"``)``#重新設著螢幕為輸入字元回顯狀態`
`sys.exit()`
`def` `is_input():`
`''' 檢測是否有管道資料輸入 '''`
`try``:`
`f` `=` `sys.stdin.fileno()` `#判斷時候有管道輸入`
`init_tty` `=` `termios.tcgetattr(f)` `#當沒有管道輸入,也沒有引數時候,顯示提示`
`return` `0`
`except``:`
`return` `1`
`def` `get_line_num(args):`
`''' 從命令列引數中獲取開始顯示的指定行`
`引數:args:從命令列獲取的引數返回值:要開始顯示的指定行  '''`
`line_num` `=` `1`
`for` `i` `in` `args:` `#匹配要從第幾行開始的行數`
`ln` `=` `re.search(r``'\+\d+'``,` `str``(i))`
`if` `ln:`
`line_num` `=` `int``(ln.group().lstrip(``'+'``))``#採用正規表示式處理去掉‘+’,得到開始顯示的行號`
`break`
`return` `line_num`
`def` `get_patstr(args):`
`'''從命令列中獲取要查詢的字串`
`引數:args:從命令列中獲取的引數為返回值:要查詢的字串:  '''`
`patstr` `=` `""`
`for` `i` `in` `args:` `#獲取要匹配的字串`
`pa` `=` `re.search(r``'(\+\/\w*[^\s])'``,` `str``(i))`
`if` `pa:`
`break`
`if` `pa:`
`patstr` `=` `str``(pa.group().lstrip(``'+/'``))`
`return` `patstr`
`def` `get_args():`
`'''用於從命令列獲取引數,解析各引數`
`返回值:(line_num,patstr,fp):要開始顯示的指定行,要查詢的字串,要操作的檔案物件 '''`
`line_num` `=` `1`
`patstr` `=` `""`
`args` `=` `sys.argv[``1``:]`
`if` `not` `args:`
`if` `is_input():` `#在沒有引數時候,判斷是否為管道命令輸入,不是提示正確輸入引數`
`fp` `=` `sys.stdin`
`return` `(line_num, patstr, fp)`
`else``:`
`usage()`
`else``:`
`if` `args[``-``1``]` `=``=` `"--help"``:`
`usage()`
`line_num` `=` `get_l`
`2000`
`ine_num(args)`
`patstr` `=` `get_patstr(args)`
`if` `'+'` `not` `in` `args[``-``1``]:`
`filename` `=` `args[``-``1``]`
`if` `not` `os.path.exists(filename):`
`print` `" 沒有那個檔案或目錄"`
`do_exit()`
`else``:`
`fp` `=` `open``(filename)`
`else``:`
`if` `not` `is_input():`
`usage()`
`else``:`
`fp` `=` `sys.stdin`
`return` `(line_num, patstr, fp)`
`def` `get_screen_size():`
`''' 用於獲取檔案顯示終端的尺寸   '''`
`global` `page_len, line_len      `
`screen` `=` `curses.initscr()      `
`page_len, line_len` `=` `screen.getmaxyx()``#獲取螢幕顯示尺寸`
`page_len` `=` `page_len` `-` `2`   `#去掉輸入命令那行,和最後要顯示more的那一行`
`curses.endwin()` `#此處不結束會導致後面顯示的亂碼`
`def` `show_more(pre_pg_len):`
`''' 等待鍵盤輸入命令 ,進行相應的處理。`
`:param pre_pg_len:螢幕改變以前儲存的可顯示的最大行數'''`
`global`  `sig_up, winsz_chg, page_len`
`ft` `=` `open``(``'/dev/tty'``)` `#開啟標準終端輸入`
`sys.stdout.flush()` `#重新整理快取輸出,否則顯示會出現問題`
`c` `=` `''`
`while` `True``:`
`try``:`
`c` `=` `ft.read(``1``)``#讀取一個字元`
`except` `IOError:`
`if` `sig_up:`
`do_exit()` `#鍵盤中斷退出程式`
`if` `c` `=``=` `" "``:`
`print` `"\033[20D\033[K"` `#控制游標回到more--反白字型的行首,刪除此行以達到more不隨文字滾動效果`
`if` `winsz_chg:` `#如果此時螢幕大小變化,第一次返回之前螢幕滿屏行數`
`winsz_chg` `=` `0`
`return` `pre_pg_len`
`else``:`
`return` `page_len` `#當輸入是空格時候,分屏顯示,顯示下一屏`
`elif` `c` `=``=` `"q"``:`
`print` `"\033[20D\033[K"`
`return` `0`          `#當輸入是"q"時,退出顯示`
`elif` `c` `=``=` `'\n'``:`
`print` `"\033[20D\033[K"``,`
`return` `1`           `#當輸入是換行符時候,多顯示一行`
`def` `skip_ln(fp, line_num):`
`''' 讀取檔案到指定開始顯示的行  '''`
`n` `=` `line_num` `-` `1`
`while` `n:`
`fp.readline()`
`if` `not` `fp:`
`return`
`n` `=` `n` `-` `1`
`def` `search(fp, patstr):`
`''' 在檔案中尋找要查詢的字串。`
`:param fp:要顯示的檔案物件   `
`:param patstr:要查詢的檢索詞  '''`
`global`  `sig_up`
`text` `=` `' '`
`while` `True``:`
`try``:`
`s` `=` `fp.read(``1``)        `
`if` `not` `s:`
`print` `"can not find the string in the file"`
`do_exit()`
`text` `=` `text` `+` `s`
`if` `patstr` `in` `text:`
`return`
`except` `IOError:`
`if` `sig_up:`
`do_exit()`
`def` `show_prog(read_size, total_size):        `
`'''  在顯示螢幕的左下角顯示反顯的"More"`
`當要顯示的是一個檔案時,同時顯示已經顯示檔案的百分比`
`當顯示的是一個管道輸入時,只顯示“More”`
`:param read_size: 已經顯示的檔案`
`:param total_size:要顯示的檔案的總大小  '''`
`if` `total_size:`
`prog` `=` `int``(read_size` `*` `100` `/` `float``(total_size))`
`print`  `"\033[7m --More--"` `+` `str``(prog)` `+` `'%'` `+` `"\033[0m"``,` `#輸出反白的文字“more”和顯示百分數`
`else``:`
`print`  `"\033[7m --More--"` `+` `"\033[0m"``,` `#輸出反白的文字“more”`
`return`
`def` `do_more(fp , line_num , patstr):`
`'''分屏顯示檔案內容`
`:param fp:要顯示的檔案物件`
`:param page_len: 可顯示的最大行數`
`:param line_len:可每行可顯示的最大位元組數   '''`
`global` `page_len, line_len`
`read_size` `=` `0`
`total_size` `=` `0`
`os.system(``"stty -F /dev/tty cbreak"``)` `#呼叫linux命令設定螢幕為不等回車`
`os.system(``"stty -F /dev/tty -echo "``)``#設定螢幕為輸入字元不回顯`
`if` `fp !``=` `sys.stdin:`
`fp.seek(``0``,` `2``)` `#獲取檔案的總位元組數,以便後來顯示輸出的百分比`
`total_size` `=` `fp.tell()`
`fp.seek(``0``,` `0``)`
`if` `line_num !``=` `1``:`
`skip_ln(fp, line_num)`
`if` `patstr:`
`search(fp, patstr)`
`try``:`
`line` `=` `fp.readline(line_len)``#按行讀取檔案,可以設定最大讀取字數,當遇到“\n”時候,將"\n"讀入結束。`
`read_size` `=` `len``(line)`
`num_lns` `=` `0`
`while` `line:`
`if` `num_lns` `=``=` `page_len:` `#每次輸出滿屏後,等待指令`
`pre_pg_len` `=` `page_len`
`show_prog(read_size, total_size)`
`reply` `=` `show_more(pre_pg_len)          `
`if` `reply` `=``=` `0``:`
`break`
`num_lns` `-``=` `reply`
`print` `line.strip(``'\n'``)` `#用,來消除print 輸出的換行符`
`sys.stdout.flush()` `#重新整理快取,否則會出現檔案顯示遲緩的問題`
`read_size` `=` `read_size` `+` `len``(line)`
`num_lns` `+``=` `1`
`line` `=` `fp.readline(line_len)`
`fp.close()`
`except` `IOError:`
`if` `sig_up:`
`do_exit()`
`if` `__name__` `=``=` `'__main__'``:`
`get_screen_size()` `#獲取顯示終端的尺寸`
`(line_num, patstr, fp)` `=` `get_args()`
`do_more(fp, line_num, patstr)`
`do_exit()`



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913713/viewspace-2648826/,如需轉載,請註明出處,否則將追究法律責任。

相關文章