咱們能夠在執行shell
腳本時實時傳遞參數從而指定某些具體的參數(在本例中包括表格的樣式、顏色等),腳本中獲取參數的格式爲$n
。其中除n
爲0
表示執行的文件名外,1
表示第一個參數,2
表示第二個參數,以此類推。html
;;
*
捕獲該值case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esac
在實例中,咱們經過第一個參數指定style
的值來選擇不一樣的表格形式(具體的表格形式由製表符向量tbs
實現)。另外當第一個參數以-h
或者--h
開頭時,咱們能夠輸出help
信息:linux
style="$1" case $style in # 根據第一個參數爲-0或-1或-2來實現不一樣的表格樣式, 即給tbs賦不一樣的值 -0) tbs=" ";; -1) tbs="└┴┘├┼┤┌┬┐ ───│││";; -2) tbs="└─┘│┼│┌─┐ ───│││";; # 若是第一個參數以%開頭, 意味着咱們能夠外部指定tbs的值 # 把style變量開頭的%去掉賦值給tbs "%"*) tbs="${style/"%"/}";; -h*|--h*) echo ' \t [ --- HELP --- ] \t command : draw_table.sh [style] [colors] < <file > \t pipo : echo -e A\\tB\\na\\tb | draw_table.sh [style] [colors] \t [style] : input 16 characters \t 1~9 is Num. keypad as table,10 is not used \t 11~13 are left,middle,right in a row \t 14~16 are left,middle,right in a column \t \t [colors]: input a list,like "-3,-4,-8" sames "-green,-yellow,-white" \t It set color,table cross ,font ,middle. Or \\033[xxm . \t And support custom color set every characters of sytle \t Like "\\033[30m,-red,-yellow,,,,,,,,,,,,," sum 16. ' exit ;; esac # ${var:-DEFAULT}: 若是var沒有被聲明, 或者其值爲空, 那麼就以$DEFAULT做爲其值 tbs="${tbs:-"+++++++++,---|||"}"
awk
命令:依次對每一行進行處理,可是相比於sed
更擅長取列,我的感受是類SQL
的文本搜索工具。
awk
的基本形式以下:git
awk [-F|-f|-v] 'BEGIN{ 命令 } pattern{ 命令 } END{ 命令 }' file
參數:shell
-F: 指定分隔符 -f: 調用腳本 -v: 使用var=value的格式定義變量
特殊變量:數組
NF: 字段數量 NR: 當前處理的行數 FILENAME: 當前文件名
三個語句塊:bash
BEGIN{ 命令 }: 執行前的命令 pattern{ 命令 }: 處理每一行執行的命令 END{ 命令 }: 執行完全部行後的命令
格式以下:框架
echo -e "\033[字背景顏色;字體顏色m字符串\033[0m" # 顏色調用始末是固定的: \033[ ; m …… \033[0m # 實例: echo -e "\033[41;36m someword \033[0m"
cols_len[NF]
:存儲了每一列的最大長度, 每列最大長度等於該列最長的元素的長度rows[NR][NF]
:將文件的每行每列的數據記錄到rows
二維數組中rows[NR][0]
:rows
第0
列存儲前一行和後一行的列數, 用於肯定當行的表格樣式colors[16]
:存儲每一個製表符對應的着色方案tbs[16]
:存儲已經着色的製表符,其中製表符樣式相似於╚ ╩ ╝ ╠ ╬ ╣ ╔ ╦ ╗ , ═ ═ ═ ║ ║ ║
,前1~9
個爲表格骨架的樣式,第10
表示着表格元素空格的填充,11~13
分別表示上邊框、中間和下邊框的鏈接符,第14~16
表示左邊框、中間和右邊框的鏈接符因爲涉及到單列,所以須要考慮到單列的狀況生成以下一些表格樣式變量:函數
# ------------------------------------------預存全部的表格線, 減小沒必要要的重複計算------------------------------------------ title_top = line_val("title_top") title_mid = line_val("title_mid") title_btm_mid = line_val("title_btm_mid") title_top_mid = line_val("title_top_mid") title_btm = line_val("title_btm") top = line_val("top") mid = line_val("mid") btm = line_val("btm") print "title_top: "title_top"\n" pring "title_mid: "title_mid"\n" print "title_btm_mid:"title_btm_mid"\n" print "title_top_mid:"title_top_mid"\n" print "title_btm: "title_btm"\n" print "top: "top"\n" print "mid: "mid"\n" print "btm: "btm"\n"
Mac
和Linux
不少命令參數不一樣是由於Mac
自帶的是BSD
系的命令,而Linux
用的是GNU
系的命令。能夠在Mac
中使用帶g
前綴的命令解決這一問題。
在Linux
下直接使用awk
命令便可,在MAC
下須要下載gawk
命令,不然awk
命令會一直報錯。工具
# 安裝GNU工具鏈 brew install coreutils brew install gawk
# 管道方法 $ echo -e "A\tB\na\tb" | sh draw_table.sh +---+---+ |,A,|,B,| +---+---+ |,a,|,b,| +---+---+ # 文件方法 $ echo -e "Your Topic\nA\tB\tC\td\na\tb\th\ts\td\n5\n78\t34" > list.txt # 第一個參數控制表格形式 $ sh draw_table.sh < list.txt +---------------------+ |,,,,,Your Topic,,,, ,| +----+----+---+---+---+ |,A,,|,B,,|,C,|,d,|,,,| +----+----+---+---+---+ |,a,,|,b,,|,h,|,s,|,d,| +----+----+---+---+---+ |,,,,,,,,,,5,,,,,,,,,,| +----+----+---+---+---+ |,78,|,34,|,,,|,,,|,,,| +----+----+---+---+---+ # 自定義模式 # 自定義表格邊框:須要用"%"開頭,前9位表示表格邊框,第10位沒有用處,第11-13 表示行的上、中、下分隔符,第14-16表示列的左、中、右分隔符 # 自定義顏色:第一個參數表示表格框架的顏色,第二個參數表示表格內容的顏色,第三個參數表示其餘顏色 # 最後能夠傳入16個顏色參數,表示style中每一個字符的顏色 $ sh draw_table.sh '%123456789 abcABC' -red,-blue,-green < list.txt 7aaaaaaaaaaaaaaaaaaaaa9 A Your Topic C 4bbbb8bbbb8bbb8bbb8bbb6 A A B B B C B d B C 4bbbb5bbbb5bbb5bbb5bbb6 A a B b B h B s B d C 4bbbb2bbbb2bbb2bbb2bbb6 A 5 C 4bbbb8bbbb8bbb8bbb8bbb6 A 78 B 34 B B B C 1cccc2cccc2ccc2ccc2ccc3
#!/bin/bash ############################################################################# # 做者:banemon # 郵箱:banemon@ # 修改: tomocat # Git: https://gitee.com/banemon/linux_sh_script # 使用說明: https://zhuanlan.zhihu.com/p/144802861 # 命令:sh draw_table.sh < file.txt 或 echo -e "A\tB\na\tb" | sh draw_table.sh # 幫助:draw_table.sh --help ############################################################################# # 表格樣式style style="$1" case ${style} in # tbs包含16個符號, 每一個符號表示的含義以下: # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 1 2 3 4 5 6 7 8 9 txt_empt top_row mid_row btm_row left_col mid_col right_col -0) tbs=" ";; -1) tbs="└┴┘├┼┤┌┬┐ ───│││";; -2) tbs="└─┘│┼│┌─┐ ───│││";; -3) tbs="╚╩╝╠╬╣╔╦╗ ═══║║║";; -4) tbs="╚═╝║╬║╔═╗ ═══║║║";; -5) tbs="╙╨╜╟╫╢╓╥╖ ───║║║";; -6) tbs="╘╧╛╞╪╡╒╤╕ ═══│││";; -7) tbs="└┴┘├┼┤┌┬┐ ─ ─│ │";; -8) tbs="└─┘│┼│┌─┐ ─ ─│ │";; -9) tbs="╚╩╝╠╬╣╔╦╗ ═ ═║ ║";; -10) tbs="╚═╝║╬║╔═╗ ═ ═║ ║";; -11) tbs="╙╨╜╟╫╢╓╥╖ ─ ─║ ║";; -12) tbs="╘╧╛╞╪╡╒╤╕ ═ ═│ │";; -13) tbs="╘╧╛╞╪╡╒╤╕ ═ ═│ │";; -14) tbs="╚╩╝╠╬╣╔╦╗ ───│││";; -15) tbs="+++++++++ ---|||";; # 自定義表格邊框:須要用"%"開頭,前9位表示表格邊框,第10位表示填充字符,第11-13 表示行的上、中、下分隔符,第14-16表示列的左、中、右分隔符 # ${string/substring/replacement}: 使用$replacement, 來代替第一個匹配的$substring, 這裏是去掉開頭的%, 另外因爲%是特殊字符須要加上雙引號(或者反斜槓) "%"*) tbs="${style/"%"/}";; # 等價於: \%*) tbs="${style/\%/}";; -h*|--h*) # -e 參數激活轉移字符, 好比\t表示製表符 echo -e ' \t [ --- HELP --- ] \t command : sh draw_table.sh [style] [colors] < <file> \t pipo : echo -e A\\tB\\na\\tb | draw_table.sh [style] [colors] \t [style] : input 16 characters \t 1~9 is Num. keypad as table,10 is not used \t 11~13 are up,middle,down in a row \t 14~16 are left,middle,right in a column \t \t -0 : \t -1 :└┴┘├┼┤┌┬┐ ───│││ -9 :╚╩╝╠╬╣╔╦╗ ═ ═║ ║ \t -2 :└─┘│┼│┌─┐ ───│││ -10 :╚═╝║╬║╔═╗ ═ ═║ ║ \t -3 :╚╩╝╠╬╣╔╦╗ ═══║║║ -11 :╙╨╜╟╫╢╓╥╖ ─ ─║ ║ \t -4 :╚═╝║╬║╔═╗ ═══║║║ -12 :╘╧╛╞╪╡╒╤╕ ═ ═│ │ \t -5 :╙╨╜╟╫╢╓╥╖ ───║║║ -13 :╘╧╛╞╪╡╒╤╕ ═ ═│ │ \t -6 :╘╧╛╞╪╡╒╤╕ ═══│││ -14 :╚╩╝╠╬╣╔╦╗ ───│││ \t -7 :└┴┘├┼┤┌┬┐ ─ ─│ │ -15 :+++++++++ ---||| \t -8 :└─┘│┼│┌─┐ ─ ─│ │ \t \t [colors]: input a list,like "-3,-4,-8" sames "-green,-yellow,-white" \t It set color,table cross ,font ,middle. Or \\033[xxm . \t And support custom color set every characters of sytle \t Like "\\033[30m,-red,-yellow,,,,,,,,,,,,," sum 16. \t \t -1|-black -5|-blue \t -2|-red -6|-purple \t -3|-green -7|-cyan \t -4|-yellow -8|-white ' exit ;; esac # 當沒有參數時, 設定tbs的默認值 tbs="${tbs:-"+++++++++,---|||"}" # 顏色 color="$2" case $color in # 1~3可用於設置本身喜歡的自定義樣式, 設置${color}的值便可 1) ;; 2) ;; 3) ;; "-"*|"\033"*) # 3位數標,詞 colors="$color" ;; "%"*) : # %號開頭的全自定義 colors="${color/"%"/}" ;; esac colors="${colors:-"-4,-8,-4"}" # 主體函數 gawk -F '\t' \ -v table_s="${tbs}" \ -v color_s="${colors}" \ 'BEGIN{ }{ # ------------------------------------------遍歷每行記錄全局變量------------------------------------------ # cols_len[NF]: 存儲了每一列的最大長度, 每列最大長度等於該列最長的元素的長度 # rows[NR][NF]: 將文件的每行每列的數據記錄到rows二維數組中 # rows[NR][0]: 第0列存儲前一行和後一行的列數, 用於肯定當行的表格樣式 # max_single_col_length: 單列行的最大長度 # ps: 因爲單列是直接合並整行的單元格, 爲圖表美觀(防止cols_len[1]由於某些特長的單列而增加), 單獨記錄單列的最大長度 # 計算單列行的最大長度 if (NF == 1) { max_single_col_length = max_single_col_length < super_length($1) ? super_length($1) : max_single_col_length rows[NR][1] = $1 } else { # 非單列行更新每一列的最大長度 for(i=1; i<=NF; i++){ cols_len[i]=cols_len[i] < super_length($i) ? super_length($i) : cols_len[i] rows[NR][i]=$i } } # 先後行狀態 if (NR == 1) {PrevNF=0} # 每行第0列存儲前一行和當前行的列數, 用於肯定當行的表格樣式 rows[NR][0] = PrevNF "," NF PrevNF=NF }END{ # ------------------------------------------colors變量着色, 生成colors和tbs變量------------------------------------------ # 構建顏色向量: colors, 長度爲16 color_sum = split(color_s,clr_id,",") if (color_sum == 3){ # 簡易自定義模式: 傳入三種顏色 for (i=1; i<=3; i++) { if (color_s ~ "-") { clr_id[i] = color_var(clr_id[i]) } } # 組建色表: 三種顏色構造colors向量 for (i=1; i<=16; i++) { if (i < 10) { colors[i] = clr_id[1] } else if (i == 10){ colors[i] = clr_id[2] } else if (i > 10){ colors[i] = clr_id[3] } } } else if (color_sum == 16){ # 全自定義模式: 傳入16種顏色 for (i=1; i<=16; i++){ if(color_s ~ "-"){ clr_id[i] = color_var(clr_id[i]) } colors[i] = clr_id[i] } } # 設置顏色變量 clr_end = "\033[0m" # shell着色的尾部標識 clr_font = colors[10] # 第10位製表符的顏色, 也就是單元格內填充字符的顏色 # 構建已着色的製表符向量: tbs, 長度16 for (i=1; i<=length(table_s); i++){ if(colors[i]=="") tbs[i] = substr(table_s, i, 1) # 獲取第i個製表符 else tbs[i] = colors[i] substr(table_s,i,1) clr_end # 給製表符着色, 例如紅色 `\033[31m製表符\033[0m` fi } # ------------------------------------------若是單列長度大於非單列最大行長度則調整各列長度------------------------------------------ max_line_len = 0 # 統計非單列的最大行長度 for (i=1; i<=length(cols_len); i++) { max_line_len = max_line_len + cols_len[i] + 2 # 每列須要包含2個空格, 防止內容和製表符緊挨着 } max_line_len = max_line_len + length(cols_len) - 1 # 多列的行最大總長度須要包含每列之間的製表符個數(列數 -1) # 若是單列最大總長度大於多列的行最大總長度時, 須要把超出的部分平均分給每列, 保證圖表美觀 diff_length = max_single_col_length + 2 - max_line_len if (diff_length > 0) { for(j=1; j<=diff_length; j++){ i = (j - 1) % length(cols_len) + 1 cols_len[i] = cols_len[i] + 1 } # 因爲增長了每列長度, 故須要調整單列最大行長度 # max_line_len = max_single_col_length + 2 } else { # 若是單列最大總長度小於行的最大總長度, 那麼單列長度要和最大行總長度保持一致 max_single_col_length = max_line_len - 2 } # ------------------------------------------預存全部的表格線, 減小沒必要要的重複計算------------------------------------------ title_top = line_val("title_top") title_mid = line_val("title_mid") title_btm_mid = line_val("title_btm_mid") title_top_mid = line_val("title_top_mid") title_btm = line_val("title_btm") top = line_val("top") mid = line_val("mid") btm = line_val("btm") # debug # print "title_top: " title_top "\n" # pring "title_mid: " title_mid "\n" # print "title_btm_mid:" title_btm_mid "\n" # print "title_top_mid:" title_top_mid" \n" # print "title_btm: " title_btm" \n" # print "top: " top" \n" # print "mid: " mid" \n" # print "btm: " btm" \n" # ------------------------------------------繪製表格------------------------------------------ row_num = length(rows) for(i=1; i<=row_num; i++){ # 解析出前一行和當前行的列數 split(rows[i][0], col_num_list, ",") prev_col_num = int(col_num_list[1]) curr_col_num = int(col_num_list[2]) # 繪製首行 if (i==1 && prev_col_num == 0) { if (curr_col_num <= 1) { # 單列 print title_top print line_val("title_txt", rows[i][1], max_single_col_length) } else if (curr_col_num >= 2) { # 多列 print top print line_val("txt", rows[i]) } } else if (prev_col_num <=1 ) { # 前一行爲單列時 if (curr_col_num <=1 ) { # 單列 print title_mid print line_val("title_txt", rows[i][1], max_single_col_length) } else if (curr_col_num >= 2) { # 多列 print title_btm_mid print line_val("txt", rows[i]) } }else if (prev_col_num >= 2) { # 前一行爲多列時 if (curr_col_num <= 1) { # 單列 print title_top_mid print line_val("title_txt", rows[i][1], max_single_col_length) } else if (curr_col_num >= 2) { # 多列 print mid print line_val("txt", rows[i]) } } # 表格底邊 if (i == row_num && curr_col_num <= 1) { # 尾行單列時 print title_btm } else if (i == row_num && curr_col_num >= 2){ # 尾行多列時 print btm } } } # 返回字符串的長度, 支持中文等雙字節字符 # eg: 內置函數length("中文")返回2, super_length("中文")返回4 function super_length(txt){ leng_base = length(txt); leng_plus = gsub(/[^\x00-\xff]/, "x", txt) # 返回Ascii碼大於255的字符匹配個數 return leng_base + leng_plus } # color_var函數: 解析形如"-n"開頭的顏色配置 function color_var(color){ if(color=="-1" ||color=="-black"){ n=30 }else if(color=="-2" || color=="-red"){ n=31 }else if(color=="-3" || color=="-green"){ n=32 }else if(color=="-4" || color=="-yellow"){ n=33 }else if(color=="-5" || color=="-blue"){ n=34 }else if(color=="-6" || color=="-purple"){ n=35 }else if(color=="-7" || color=="-cyan"){ n=36 }else if(color=="-8" || color=="-white"){ n=37 }else if(color=="-0" || color=="-reset"){ n=0 }else{ n=0 } return "\033[" n "m" } # ------------------------------------------生成繪製內容的函數------------------------------------------ # 參數: part繪製的位置; txt繪製的文本內容; cell_lens繪製的單元格長度 # eg: tbs爲已着色的製表符 ╚ ╩ ╝ ╠ ╬ ╣ ╔ ╦ ╗ , ═ ═ ═ ║ ║ ║ # TODO: cell_len, line, i這三個參數的意義何在, awk的特殊用法? function line_val(part, txt, cell_lens, cell_len, line, i) { # 更新本次行標 if (part=="top") { tbs_l=tbs[7] tbs_m=tbs[8] tbs_r=tbs[9] tbs_b=tbs[11] } else if (part=="mid") { tbs_l=tbs[4] tbs_m=tbs[5] tbs_r=tbs[6] tbs_b=tbs[12] } else if (part=="txt") { # tbs[10]爲填充字符, 用於填充單元格內的空格 tbs_l=tbs[14] tbs[10] tbs_m=tbs[10] tbs[15] tbs[10] tbs_r=tbs[10] tbs[16] tbs_b=tbs[10] } else if (part=="btm"){ tbs_l=tbs[1] tbs_m=tbs[2] tbs_r=tbs[3] tbs_b=tbs[13] } else if (part=="title_top"){ tbs_l=tbs[7] tbs_m=tbs[11] tbs_r=tbs[9] tbs_b=tbs[11] } else if (part=="title_top_mid"){ tbs_l=tbs[4] tbs_m=tbs[2] tbs_r=tbs[6] tbs_b=tbs[12] } else if (part=="title_mid"){ tbs_l=tbs[4] tbs_m=tbs[12] tbs_r=tbs[6] tbs_b=tbs[12] } else if (part=="title_txt"){ tbs_l=tbs[14] tbs[10] tbs_m=tbs[10] tbs[15] tbs[10] tbs_r=tbs[10] tbs[16] tbs_b=tbs[10] } else if (part=="title_btm"){ tbs_l=tbs[1] tbs_m=tbs[13] tbs_r=tbs[3] tbs_b=tbs[13] } else if (part=="title_btm_mid"){ tbs_l=tbs[4] tbs_m=tbs[8] tbs_r=tbs[6] tbs_b=tbs[12] } # title行只有一列文本 if (part == "title_txt") { cols_count=1 } else { cols_count = length(cols_len) } # 遍歷該行全部列, 構造改行的內容 line_content = "" # 對於一行內的每個單元格, 計算單元格文本cell_txt 和 對應的空白字符填充數fill_len for (i=1; i<=cols_count; i++) { if (part == "txt") { # 多列左對齊 cell_txt = txt[i] fill_len = cols_len[i] - super_length(cell_txt) }else if(part=="title_txt"){ # 單列居中 cell_txt = txt fill_len = (cell_lens - super_length(cell_txt)) / 2 is_need_fix = (cell_lens - super_length(cell_txt)) % 2 # 若是填充字符長度非偶數則須要fix } else { cell_txt = "" fill_len = cols_len[i] + 2 } # 單元格文本着色 cell_txt = clr_font cell_txt clr_end # 單元格內空白補全 if (part == "title_txt") { # 單列居中, 在單元格文本兩側補全空格字符 for (cell_len=1; cell_len <= fill_len; cell_len++) { cell_txt = tbs_b cell_txt tbs_b } # 單列非偶長度補全 if (is_need_fix == 1) { cell_txt = cell_txt " " } }else{ # 多列左對齊 for (cell_len=1; cell_len<=fill_len; cell_len++) { cell_txt = cell_txt tbs_b } } # 首格 if (i == 1) { line_content = line_content cell_txt } else { # 中格 line_content = line_content tbs_m cell_txt } # 尾格 if ( i == cols_count ) { line_content = line_content tbs_r } } # 返回行: tbs_l表示最左側的表格樣式, line_content表示該行的內容 return tbs_l line_content } '
實際中常常碰到日誌採集分析的問題,能夠在shell
腳本加入以下的語句用於可視化輸出表格數據:字體
echo -e "Module Log Analyse Function Name\tCount Function1\t20 Function2\t1113 Function3\t257 Function4\t113" | sh draw_table.sh -4 -red,-white,-blue
[1] https://www.runoob.com/linux/...
[2] https://www.cnblogs.com/gaoch...
[3] https://www.cnblogs.com/nb-bl...
[4] https://www.cnblogs.com/knowl...