那么要如何才能編寫出這個特效的圣誕樹呢?
下面一口君手把手教大家!
只想運行腳本的同學可以跳到最后面!
一、shell腳本知識
1. shell變量
變量是任何一種編程語言都必不可少的組成部分,變量用來存放各種數據。腳本語言在定義變量時通常不需要指明類型,直接賦值就可以,Shell 變量也遵循這個規則。Shell 支持以下三種定義變量的方式:
- variable=value
- variable='value'
- variable="value"
variable 是變量名,value 是賦給變量的值。如果 value 不包含任何空白符(例如空格、Tab 縮進等),那么可以不使用引號;如果 value 包含了空白符,那么就必須使用引號包圍起來。使用單引號和使用雙引號也是有區別的,稍后我們會詳細說明。
注意,賦值號=的周圍不能有空格,這可能和你熟悉的大部分編程語言都不一樣。
Shell 變量的命名規范和大部分編程語言都一樣:
- 變量名由數字、字母、下劃線組成;
- 必須以字母或者下劃線開頭;
- 不能使用 Shell 里的關鍵字(通過 help 命令可以查看保留關鍵字)。
使用變量
使用一個定義過的變量,只要在變量名前面加美元符號$即可,如:
- skill="C、Linux"
- echo "I am good at ${skill}Script"
變量名外面的花括號{ }是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界. 如果不給 skill 變量加花括號,寫成echo "I am good at $skillScript",解釋器就會把 $skillScript 當成一個變量(其值為空),代碼執行結果就不是我們期望的樣子了。
修改變量的值
- lin=2
- let lin++
單引號和雙引號的區別
定義變量時,變量的值可以由單引號' '包圍,也可以由雙引號" "包圍,它們到底有什么區別呢?不妨以下面的代碼為例來說明:
- #!/bin/bash
- name="一口Linux"
- gzh1='公眾號:${name}'
- gzh2="C語言中文網:${name}"
- echo $gzh1
- echo $gzh2
運行結果:
- 公眾號:${name}
- 公眾號:一口Linux
以單引號' '包圍變量的值時,單引號里面是什么就輸出什么,即使內容中有變量和命令(命令需要反引起來)也會把它們原樣輸出。這種方式比較適合定義顯示純字符串的情況,即不希望解析變量、命令等的場景。
以雙引號" "包圍變量的值時,輸出時會先解析里面的變量和命令,而不是把雙引號中的變量名和命令原樣輸出。這種方式比較適合字符串中附帶有變量和命令并且想將其解析后再輸出的變量定義。
建議:如果變量的內容是數字,那么可以不加引號;如果真的需要原樣輸出就加單引號;其他沒有特別要求的字符串等最好都加上雙引號,定義變量時加雙引號是最常見的使用場景。
2. trap
trap命令是專用于捕捉信號的。比如像ctrl+c發送給終端的中斷信號等等。在捕捉到信號之后,可以進行一系列的操作。
用法:
- trap 'COMMAND' INT
COMMAND表示trap命令接收到INT信號后要執行的動作什么。
可以捕捉的信號有:HUP INT等 不適用捕捉的信號:KILL TERM
信號回應方式
trap捕捉到信號之后,可以有三種反應方式:
1、執行一段程序來處理這一信號
2、接受信號的默認操作
3、忽視這一信號
它有三種形式分別對應三種不同的信號回應方式 第一種:
- trap ""commands"" signal-list
當腳本收到signal-list清單內列出的信號時,trap命令執行雙引號中的命令.
第二種:
- trap signal-list
trap不指定任何命令,接受信號的默認操作.默認操作是結束進程的運行. 第三種:
- trap "" "" signal-list
trap命令指定一個空命令串,允許忽視信號.
使用trap -l命令可以查看信號有哪些:
- # trap -l
- 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
- 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
- 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
- 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
- 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
- 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
- 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
- 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
- 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
- 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
- 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
- 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
- 63) SIGRTMAX-1 64) SIGRTMAX
3. clear
清除終端屏幕
4. tput
tput 命令將通過 terminfo 數據庫對您的終端會話進行初始化和操作。通過使用tput,您可以更改幾項終端功能,如移動或更改光標、更改文本屬性,以及清除終端屏幕的特定區域。
光標屬性
- tput sc ##記錄光標位置
- tput cup x y ###移動光標至x列y行
- tput rc ##返回光標位置
- tput civis ##隱藏光標
- tput cnorm ## 顯示光標
- tput setaf ColorNumber ## 設置前景色
- tput setab ColorNumber ##設置背景色
- tput clear # 清除屏幕
- tput cup x y # 光標按設定坐標點移動
文本屬性
- tput blink # 文本閃爍
- tput bold # 文本加粗
- tput el # 清除到行尾
- tput smso # 啟動突出模式
- tput rmso # 停止突出模式
- tput smul # 下劃線模式
- tput rmul # 取消下劃線模式
- tput sgr0 # 恢復默認終端
- tput rev # 反相終端
此外,還可以改變文本的顏色
- tput setb 顏色代號
- tput setf 顏色代號
舉例
- #加粗
- bold=$(tput bold)
- #下劃線
- underline=$(tput sgr 0 1)
- #重置規則
- reset=$(tput sgr0)
- #紅色
- red=$(tput setaf 1)
- #綠色
- green=$(tput setaf 2)
下面是一個帶閃爍功能的時鐘
- #!/bin/bash
- for ((i=0;i<8;i++))
- do
- tput sc; tput civis # 記錄光標位置,及隱藏光標
- tput blink; tput setf $i # 文本閃爍,更改文本顏色
- echo -ne $(date +'%Y-%m-%d %H:%M:%S') # 顯示時間
- sleep 1
- tput rc # 恢復光標到記錄位置
- done
- tput el; tput cnorm # 退出時清理終端,恢復光標顯示
效果
5. for循環
for循環的運作方式,是講串行的元素意義取出,依序放入指定的變量中,然后重復執行含括的命令區域(在do和done 之間),直到所有元素取盡為止。
其中,串行是一些字符串的組合,彼此用$IFS所定義的分隔符(如空格符)隔開,這些字符串稱為字段。
for的語法結構如下:
- 1. for 變量 in 串行
- 2. do
- 3. 執行命令
- 4. done
說明:
行1,講串行中的字段迭代放入變量中 行2-4,接著將重復執行do和done之間的命令區域,直到串行中每一個字段均處理過為止。
舉例 用for循環在家目錄下創建aaa1-aaa10,然后在aaa1-aaa10創建bbb1-bbb10的目錄
- 1. #!/bin/bash
- 2. for k in $( seq 1 10 )
- 3. do
- 4. mkdir /home/peng/aaa${k}
- 5. cd /home/peng/aaa${k}
- 6. for l in $( seq 1 10 )
- 7. do
- 8. mkdir bbb${l}
- 9. cd /home/peng/aaa${k}
- 10. done
- 11. cd ..
- done
列出var目錄下各子目錄占用磁盤空間的大小。
- #!/bin/bash
- DIR="/var"
- cd $DIR
- for k in $(ls $DIR)
- do
- [ -d $k ] && du -sh $k
- done
6. while循環
while循環的語法:
- 1. while 條件測試
- 2. do
- 3. 執行命令
- 4. done
說明:
- 行1,首先進行條件測試,如果傳回值為0(條件測試為真),則進入循環,執行命令區域,否則
- 不進入循環,介紹while 命令
- 行3,執行命令區域,這些命令中,應該要有改變條件測試的命令,這樣,才有機會在
- 有限步驟后結束執行while循環(除非想要執行無窮循環)。
- 行4,回到行1,執行while命令
流程圖:
實例 計算1+2+3…………10
- #!/bin/bash
- declare -i i=1
- declare -i sum=0
- while ((i<=10))
- do
- let sum+=i
- let ++i
- done
- echo $sum
二、圣誕樹腳本文件
- #!/bin/bash
- #用shell編寫一個圣誕樹
- #創建時間2021-12-23
- trap "tput reset; tput cnorm; exit" 2
- clear
- tput civis
- lin=2
- col=$(($(tput cols) / 2))
- c=$((col-1))
- est=$((c-2))
- color=0
- tput setaf 2; tput bold
- # 打印樹葉
- for ((i=1; i<20; i+=2))
- {
- tput cup $lin $col
- for ((j=1; j<=i; j++))
- {
- echo -n \*
- }
- let lin++
- let col--
- }
- tput sgr0; tput setaf 3
- # 打印樹干
- for ((i=1; i<=2; i++))
- {
- tput cup $((lin++)) $c
- echo '||'
- }
- new_year=$(date +'%Y')
- let new_year++
- tput setaf 222; tput bold
- tput cup $lin $((c - 10)); echo $new_year 圣 誕 節 快 樂?。?!
- color=122
- tput setaf $color; tput bold
- tput cup $((lin + 1)) $((c - 10)); echo 關注公眾號: 一口Linux!
- let c++
- k=1
- #裝飾一下
- while true; do
- for ((i=1; i<=35; i++)) {
- # Turn off the lights
- [ $k -gt 1 ] && {
- tput setaf 2; tput bold
- tput cup ${line[$[k-1]$i]} ${column[$[k-1]$i]}; echo \*
- unset line[$[k-1]$i]; unset column[$[k-1]$i]
- }
- li=$((RANDOM % 9 + 3))
- start=$((c-li+2))
- co=$((RANDOM % (li-2) * 2 + 1 + start))
- tput setaf $color; tput bold
- tput cup $li $co
- echo o
- line[$k$i]=$li
- column[$k$i]=$co
- color=$(((color+1)%8))
- sh=1
- #for l in M O N E Y
- for l in 一 口 Li nu x!
- do
- tput cup $((lin+1)) $((c+sh))
- echo $l
- let sh++
- let sh++
- sleep 0.02
- done
- }
- k=$((k % 2 + 1))
- done
三、執行腳本
- root@ubuntu:/home/peng/work/test# chmod 777 peng.sh
- root@ubuntu:/home/peng/work/test# ./peng.sh
還等什么呢?抓緊運行起來吧!
本文轉載自微信公眾號「一口Linux」
原文鏈接:https://mp.weixin.qq.com/s/QzhzGEjSrxWgg_FGbCtjLg