• 正文
  • 相关推荐
申请入驻 产业图谱

教你用shell脚本实现一颗圣诞树!

02/06 15:17
507
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

在此一口君特地用shell脚本画了一个圣诞树!先来看下执行结果吧!

那么要如何才能编写出这个特效的圣诞树呢??下面一口君手把手教大家!

只想运行脚本的同学可以跳到最后面!

一、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』号主彭老师,拥有15年嵌入式开发经验和培训经验。曾任职ZTE,某研究所,华清远见教学总监。拥有多篇网络协议相关专利和软件著作。精通计算机网络、Linux系统编程、ARM、Linux驱动、龙芯、物联网。原创内容基本从实际项目出发,保持原理+实践风格,适合Linux驱动新手入门和技术进阶。