在此一口君特地用shell腳本畫(huà)了一個(gè)圣誕樹(shù)!先來(lái)看下執(zhí)行結(jié)果吧!
那么要如何才能編寫(xiě)出這個(gè)特效的圣誕樹(shù)呢??下面一口君手把手教大家!
只想運(yùn)行腳本的同學(xué)可以跳到最后面!
一、shell腳本知識(shí)
1. shell變量
變量是任何一種編程語(yǔ)言都必不可少的組成部分,變量用來(lái)存放各種數(shù)據(jù)。腳本語(yǔ)言在定義變量時(shí)通常不需要指明類(lèi)型,直接賦值就可以,Shell 變量也遵循這個(gè)規(guī)則。Shell 支持以下三種定義變量的方式:
variable=value
variable='value'
variable="value"
variable 是變量名,value 是賦給變量的值。如果 value 不包含任何空白符(例如空格、Tab 縮進(jìn)等),那么可以不使用引號(hào);如果 value 包含了空白符,那么就必須使用引號(hào)包圍起來(lái)。使用單引號(hào)和使用雙引號(hào)也是有區(qū)別的,稍后我們會(huì)詳細(xì)說(shuō)明。
注意,賦值號(hào)=的周?chē)荒苡锌崭?,這可能和你熟悉的大部分編程語(yǔ)言都不一樣。
Shell 變量的命名規(guī)范和大部分編程語(yǔ)言都一樣:
- 變量名由數(shù)字、字母、下劃線(xiàn)組成;必須以字母或者下劃線(xiàn)開(kāi)頭;不能使用 Shell 里的關(guān)鍵字(通過(guò) help 命令可以查看保留關(guān)鍵字)。
使用變量
使用一個(gè)定義過(guò)的變量,只要在變量名前面加美元符號(hào)$
即可,如:
skill="C、Linux"
echo?"I?am?good?at?${skill}Script"
變量名外面的花括號(hào){ }
是可選的,加不加都行,加花括號(hào)是為了幫助解釋器識(shí)別變量的邊界.
如果不給 skill 變量加花括號(hào),寫(xiě)成echo "I am good at $skillScript"
,解釋器就會(huì)把 $skillScript
當(dāng)成一個(gè)變量(其值為空),代碼執(zhí)行結(jié)果就不是我們期望的樣子了。
修改變量的值
lin=2
let?lin++
單引號(hào)和雙引號(hào)的區(qū)別
定義變量時(shí),變量的值可以由單引號(hào)' '
包圍,也可以由雙引號(hào)" "
包圍,它們到底有什么區(qū)別呢?不妨以下面的代碼為例來(lái)說(shuō)明:
#!/bin/bash
name="一口Linux"
gzh1='公眾號(hào):${name}'
gzh2="C語(yǔ)言中文網(wǎng):${name}"
echo?$gzh1
echo?$gzh2
運(yùn)行結(jié)果:
公眾號(hào):${name}
公眾號(hào):一口Linux
以單引號(hào)' '
包圍變量的值時(shí),單引號(hào)里面是什么就輸出什么,即使內(nèi)容中有變量和命令(命令需要反引起來(lái))也會(huì)把它們?cè)瓨虞敵?。這種方式比較適合定義顯示純字符串的情況,即不希望解析變量、命令等的場(chǎng)景。
以雙引號(hào)" "
包圍變量的值時(shí),輸出時(shí)會(huì)先解析里面的變量和命令,而不是把雙引號(hào)中的變量名和命令原樣輸出。這種方式比較適合字符串中附帶有變量和命令并且想將其解析后再輸出的變量定義。
建議:如果變量的內(nèi)容是數(shù)字,那么可以不加引號(hào);如果真的需要原樣輸出就加單引號(hào);其他沒(méi)有特別要求的字符串等最好都加上雙引號(hào),定義變量時(shí)加雙引號(hào)是最常見(jiàn)的使用場(chǎng)景。
2. trap
trap命令是專(zhuān)用于捕捉信號(hào)的。比如像ctrl+c發(fā)送給終端的中斷信號(hào)等等。在捕捉到信號(hào)之后,可以進(jìn)行一系列的操作。
用法:
trap??'COMMAND'?INT?????
COMMAND表示trap命令接收到INT信號(hào)后要執(zhí)行的動(dòng)作什么。
可以捕捉的信號(hào)有:HUP INT
等
不適用捕捉的信號(hào):KILL TERM
信號(hào)回應(yīng)方式
trap捕捉到信號(hào)之后,可以有三種反應(yīng)方式:
- 1、執(zhí)行一段程序來(lái)處理這一信號(hào)2、接受信號(hào)的默認(rèn)操作3、忽視這一信號(hào)
它有三種形式分別對(duì)應(yīng)三種不同的信號(hào)回應(yīng)方式
第一種:
trap?""commands""?signal-list
當(dāng)腳本收到signal-list清單內(nèi)列出的信號(hào)時(shí),trap命令執(zhí)行雙引號(hào)中的命令.
第二種:
trap?signal-list
trap不指定任何命令,接受信號(hào)的默認(rèn)操作.默認(rèn)操作是結(jié)束進(jìn)程的運(yùn)行.
第三種:
trap?""?""?signal-list
trap命令指定一個(gè)空命令串,允許忽視信號(hào).
使用trap -l命令可以查看信號(hào)有哪些:
#?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 命令將通過(guò) terminfo 數(shù)據(jù)庫(kù)對(duì)您的終端會(huì)話(huà)進(jìn)行初始化和操作。通過(guò)使用tput,您可以更改幾項(xiàng)終端功能,如移動(dòng)或更改光標(biāo)、更改文本屬性,以及清除終端屏幕的特定區(qū)域。
光標(biāo)屬性
tput?sc??????????##記錄光標(biāo)位置
tput?cup?x?y?????###移動(dòng)光標(biāo)至x列y行
tput?rc??????????##返回光標(biāo)位置
tput?civis???????##隱藏光標(biāo)
tput?cnorm???????##?顯示光標(biāo)
tput?setaf?ColorNumber?##?設(shè)置前景色
tput?setab?ColorNumber?##設(shè)置背景色
tput?clear??????#?清除屏幕
tput?cup?x?y????#?光標(biāo)按設(shè)定坐標(biāo)點(diǎn)移動(dòng)
文本屬性
tput?blink??????#?文本閃爍
tput?bold???????#?文本加粗
tput?el?????????#?清除到行尾
tput?smso???????#?啟動(dòng)突出模式
tput?rmso???????#?停止突出模式
tput?smul???????#?下劃線(xiàn)模式
tput?rmul???????#?取消下劃線(xiàn)模式
tput?sgr0???????#?恢復(fù)默認(rèn)終端
tput?rev????????#?反相終端
此外,還可以改變文本的顏色
tput?setb?顏色代號(hào)
tput?setf?顏色代號(hào)
舉例
#加粗
bold=$(tput?bold)
#下劃線(xiàn)
underline=$(tput?sgr?0?1)
#重置規(guī)則
reset=$(tput?sgr0)
#紅色
red=$(tput?setaf?1)
#綠色
green=$(tput?setaf?2)
下面是一個(gè)帶閃爍功能的時(shí)鐘
#!/bin/bash
for?((i=0;i<8;i++))
do
????????tput?sc;?tput?civis?????????????????????#?記錄光標(biāo)位置,及隱藏光標(biāo)
????????tput?blink;?tput?setf?$i????????????????#?文本閃爍,更改文本顏色
????????echo?-ne?$(date?+'%Y-%m-%d?%H:%M:%S')???#?顯示時(shí)間
????????sleep?1
????????tput?rc?????????????????????????????????#?恢復(fù)光標(biāo)到記錄位置
done
tput?el;?tput?cnorm?????????????????????????????#?退出時(shí)清理終端,恢復(fù)光標(biāo)顯示
效果
5. for循環(huán)
for循環(huán)的運(yùn)作方式,是講串行的元素意義取出,依序放入指定的變量中,然后重復(fù)執(zhí)行含括的命令區(qū)域(在do和done 之間),直到所有元素取盡為止。
其中,串行是一些字符串的組合,彼此用$IFS所定義的分隔符(如空格符)隔開(kāi),這些字符串稱(chēng)為字段。
for的語(yǔ)法結(jié)構(gòu)如下:
1.?for?變量?in?串行
2.?do
3.????執(zhí)行命令
4.?done
說(shuō)明:
行1,講串行中的字段迭代放入變量中
行2-4,接著將重復(fù)執(zhí)行do和done之間的命令區(qū)域,直到串行中每一個(gè)字段均處理過(guò)為止。
舉例
用for循環(huán)在家目錄下創(chuàng)建aaa1-aaa10,然后在aaa1-aaa10創(chuàng)建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目錄下各子目錄占用磁盤(pán)空間的大小。
#!/bin/bash
DIR="/var"
cd?$DIR
for?k?in?$(ls?$DIR)
do
??[?-d?$k?]?&&?du?-sh?$k
done
6. while循環(huán)
while循環(huán)的語(yǔ)法:
1.?while?條件測(cè)試
2.?do
3.???執(zhí)行命令
4.?done
說(shuō)明:
行1,首先進(jìn)行條件測(cè)試,如果傳回值為0(條件測(cè)試為真),則進(jìn)入循環(huán),執(zhí)行命令區(qū)域,否則
不進(jìn)入循環(huán),介紹while?命令
行3,執(zhí)行命令區(qū)域,這些命令中,應(yīng)該要有改變條件測(cè)試的命令,這樣,才有機(jī)會(huì)在
有限步驟后結(jié)束執(zhí)行while循環(huán)(除非想要執(zhí)行無(wú)窮循環(huán))。
行4,回到行1,執(zhí)行while命令
流程圖:實(shí)例
計(jì)算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
二、圣誕樹(shù)腳本文件
#!/bin/bash
#用shell編寫(xiě)一個(gè)圣誕樹(shù)
#創(chuàng)建時(shí)間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
#?打印樹(shù)葉
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
#?打印樹(shù)干
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??圣?誕?節(jié)?快?樂(lè)?。?!
color=122
tput?setaf?$color;?tput?bold
tput?cup?$((lin?+?1))?$((c?-?10));?echo?關(guān)注公眾號(hào):??一口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
三、執(zhí)行腳本
root@ubuntu:/home/peng/work/test#?chmod?777?peng.sh
root@ubuntu:/home/peng/work/test#?./peng.sh?
還等什么呢?抓緊運(yùn)行起來(lái)吧!