那么要如何才能编写出这个特效的圣诞树呢?
下面一口君手把手教大家!
只想运行脚本的同学可以跳到最后面!
一、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捕捉到信号之后,可以有三种反应方式:
执行一段程序来处理这一信号
接受信号的默认操作
忽视这一信号
它有三种形式分别对应三种不同的信号回应方式 第一种:
- 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」