shell脚本书写规范
shell脚本编程规范与书写习惯
1.开头加脚本解释器
2.附带作者及版权信息
3.脚本扩展名为 *.sh
4.脚本存放在固定的目录下
5.脚本尽量不使用中文
6.成对的符号 一次性书写完成
7.循环格式一次输入完成
8.中括号首尾要有一个空格
shell脚本的注释
# 后面的的内容一般为注释,可以使用vim 命令模式ctrl+v 可视化模块添加。也可以使用如下方法:
:<<EOF
需要注释的内容
EOF
注:结尾的EOF必须从行首写,不能有空格, :冒号在shell中也是命令,表示深度不做。
例如:
#!/bin/bash
echo "123"
:<<EOF
echo "234"
echo "345"
EOF
shell脚本的执行
1.当脚本每可执行权限或脚本开头文件没有指定解释器时推荐使用:
bash script_name
sh script_name
2.指定当前路径下执行脚本(脚本需要有执行权限)
chmod +x script_name
再执行
/path/script_name
./script_name
3.其他
cat script_name | sh
source script_name
sh < script_name
. script_name
父shell和子shell的概念
在A脚本运行b脚本,那么可以称b为A的子shell,A为父shell。
父shell和子shell之间是不能调用的,若需要调用变量需要使用source或 . 点。
例如:
[root@m01 scripts]# cat 2.sh
#!/bin/bash
user=`whoami`
[root@m01 scripts]# sh 2.sh
[root@m01 scripts]# echo $user
[root@m01 scripts]# user=`whoami`
[root@m01 scripts]# echo $user
root
[root@m01 scripts]# unset user
[root@m01 scripts]# echo $user
[root@m01 scripts]#
# 使用source调用是可以读取到变量的
[root@m01 scripts]# source 2.sh
[root@m01 scripts]# echo $user
root
总结:
使用source 和 . 点来执行脚本,相当于在shell下面执行脚本,变量互相可以调用。
bash和sh执行脚本,等于开启了一个新的shell,或者说开启了一个子shell,无法读取父定义的变量。
declare命令
声明变量,设置或显示变量的值和属性
例:
声明变量
[root@m01 scripts]# declare B=aaa
[root@m01 scripts]# echo $B
aaa
unset命令
删除指定shell变量或函数
参数:
-f 仅删除函数
-v 仅山粗变量(不包括只读变量)
-n 删除具有引用属性的变量名(如果该选项存在)
案例:
[root@m01 scripts]# a=123
[root@m01 scripts]# echo $a
123
[root@m01 scripts]# unset a #删除指定shell变量
[root@m01 scripts]# echo $a
[root@m01 scripts]#
set命令
显示或设置特殊及shell变量。
set命令注意作用是显示系统中已经存在的shell变量,以及设置shell变量的新变量值。set命令不能定义新的shel变量,如有要定义新的变量可以使用declare命令以 “变量名=值” 的格式定义。
参数:
-a 标示以修改的变量,以供输出值环境变量
-f 取消使用通配符
-n 只读指令,而不实际执行
例:
[root@m01 scripts]# set |grep LANG
LANG=en_US.UTF-8
env命令
显示系统中已存在的环境变量
例:
过滤系统环境变量
[root@m01 scripts]# env |grep LANG
LANG=en_US.UTF-8
tee命令
从标注输入读取数据并重定向到标准输出和文件;要食醋胡的文件可以是一个或多个。
参数:
-a 追加到文件中而不是覆盖
案例:
将信息通过管道符输出到标准输出并覆盖写入到文件中,加-a参数是追加而不是覆盖
[root@m01 scripts]# cat 2.sh | tee 2.txt
#!/bin/bash
user=`whoami`
[root@m01 scripts]# cat 2.txt
#!/bin/bash
user=`whoami`
readonly命令
标记shell变量或函数为只读
主要用途:
定义一个到多个变量并设置为只读属性
显示全部包含只读属性的变量/函数
参数:
-a 指向数组
-A 指向关联数组
-f 指向函数
-p 显示全部只读变量
-- 在它之后的选项无效
只读变量:是指不能被清除或重新赋值的变量。declare无法去除只读属性,unset不能删除只读变量。
案例:
标记变量为只读变量
[root@m01 scripts]# A=XXX
[root@m01 scripts]# readonly A
[root@m01 scripts]# A=yyy
-bash: A: readonly variable
[root@m01 scripts]# unset A=yyy
-bash: unset: `A=yyy': not a valid identifier
删除只读变量
cat << EOF| gdb
attach $$
call unbind_variable("变量名")
detach
EOF
变量知识
什么是变量
变量源自数学,是计算机语言中能存储计算结果或能表示值的抽象概念。
shell变量特性
默认情况下,在bash shell中是不会区分变量是什么类型的,如:常见的变量类型为整数,字符串,小数等。
shell变量分类
变量可以分为两类:
环境变量(全局变量):可以在创建他们的shell及其派生出来的任意子进程中使用,环境变量又可以分为自定义环境变量和bash内置环境变量。
普通变量(局部变量):只能在创建他们的shell函数或shell脚本中使用,普通变量一般由开发者在开发脚本程序是创建。
定义环境变量
如:PS1;PATH;HOME;UID等系统固有的,默认就表示一定的意义。
系统级:/etc/profile /etc/bashrc
用户级:~/.bash_profile ~/.bashrc ~/.bash_logout ~/.bash_history
设置环境变量有三种方法:
第一种:
export A=1
第二种:
B=2
export B
第三种:
declare -x C=3
总结:
定义环境变量尽量大写;
使环境变量全局生效,可以写入/etc/profile文件中。
显示环境变量使用env和set命令
取消环境变量是 unset + 变量名1 变量名2 ...
定义永久变量
本地变量:用户私有变量,只有本用户可以使用,保存在家目录下的.bash_profile,.bashrc文件中
全局变量:所有用户都可以使用,保存在/etc/profile,/etc/bashrc文件中
例如:
本地变量
[root@www ~]# tail -1 ~/.bash_profile
name='ccc'
全局变量
[root@www ~]# tail -1 /etc/profile
export age=18
环境变量初始化与对于文件生效顺序
先加载/etc/profile;然后加载~/.bash_profile;再加载~/.bashrc;最后加载/etc/bashrc
普通变量(局部变量)
当前用户或脚本种生效,离开当前用户或脚本失效。
变量名:
规则:字母,数字,下划线,三种组合,以字母开头,中间不能有空格,不能使用数字开头。
要求:见名知意
驼峰语法:首个单词字母小写,其余单词首字母大写。
例如:
MyAge=18
my_age=18
myAge=18
变量内容:
字符串:
变量名=value #不加引号,解析变量或者命令,然后输出,出数字选择不加引号,value 值。
变量名='value' #加单引号,所见即所得
变量="value" #加双引号,解析变量或命令,然后输出,字符串默认选择双引号,可以把要定义的内容作为一个整体。
命令变量:
变量名=`ls`
变量名=$(ls)
普通变量定义及输出小结:
变量名:
1)变量名定义要有一定的命令规范,并且要见名知意,推荐使用驼峰语法,myAge=18
2)变量名仅能使用字母,数字,下划线中的任意多个字符,并且尽量以字母开头
变量内容:
在脚本中定义普通字符串变量,尽量把变量的内容用双引号括起来
单纯数字的变量内容可以不加引号
希望变量的内容原样输出加单引号
希望变量值引用命令并且获取命令结果使用反引号或$()
赋值符号:
变量定义是赋值符号(=),赋值符号两端不要有空格
变量输出:
使用或输出变量的内容可以使用$变量名,例:echo $变量名
若变量名后面有其他字符连接的时候,就必须给变量加上大括号{};例如:$db_t 就要改写成${db}_
特殊重要变量
特殊位置参数变量
符号 | 作用说明 |
---|---|
$0 | 获取当前执行shell脚本的文件名,如果执行脚本带路径,那么就包括脚本路径 |
$n | 获取当前执行的shell脚本的第n个参数值,n=1…9,当n为0时如上;如果n>9,则大括号括起来,如${10},这样才能代表第10个参数 |
$# | 获取当前执行的shell脚本后面接的参数的总个数 |
$* | 获取当前shell脚本所有传参的参数,不加引号同
@
;
如
果
给
@;如果给
@;如果给*加上双引号,例如: "$*" ,则表示将所有的参数视为单个字符串,相当于"$1 $2 $3" |
$@ | 获取当前shell脚本所有传参的参数,不加引号同 ∗ , 如 果 给 * ,如果给 ∗,如果给@加上双引号,例如:"$@",则表示将所有的参数视为不同的独立字符串,相当于"$1" “$2” “ 3 " " . . . " , 这 是 将 多 参 数 传 递 给 其 他 程 序 的 最 佳 方 式 , 因 为 它 会 保 留 所 有 内 嵌 的 每 个 参 数 里 的 任 何 空 白 。 当 " 3" "...",这是将多参数传递给其他程序的最佳方式,因为它会保留所有内嵌的每个参数里的任何空白。当" 3""...",这是将多参数传递给其他程序的最佳方式,因为它会保留所有内嵌的每个参数里的任何空白。当"@“和”$*” 都加上双引号时,二者有区别,都不加双引号,二者无区别。 |
案例:
1. $0,输出当前执行脚本文件名,如果有路径则输出脚本路径
[root@m01 scripts]# cat test.sh
#!/bin/bash
echo $0
[root@m01 scripts]# sh test.sh yyy
test.sh
[root@m01 scripts]# sh /scripts/test.sh
/scripts/test.sh
2.$1,$2,...$10,$11...$n,获取当前执行脚本的第n个参数
$1,$2脚本后面接的第1,2个参数
[root@m01 scripts]# sh test.sh pp qq
pp qq
大于9的,如$10需要加大括号
不加括号,$10成了识别成了$1+0的组合,也就是a0
[root@m01 scripts]# cat test.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[root@m01 scripts]# bash test.sh {a..z}
a b c d e f g h i a0 a1 a2 a3 a4 a5
加大括号后取到了12个字母
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12}
[root@m01 scripts]# bash test.sh {a..z}
a b c d e f g h i j k l
3.$#示例,表示当前shell脚本后面接的参数的总和
[root@m01 scripts]# cat test.sh
#!/bin/bash
echo $#
[root@m01 scripts]# sh test.sh gg
1
[root@m01 scripts]# sh test.sh {1..100}
100
4.$*与$@,当需要接收脚本后面所有参数时, 但是又不知道参数个数或参数太多就可以使用这两个变量
不加引号,二者无区别,用来获取脚本后所有参数
加引号,二者区别如下:
[root@m01 scripts]# cat test.sh
#!/bin/bas
for arg in "$*"
do
echo $arg
done
echo ------------
for arg1 in "$@"
do
echo $arg1
done
[root@m01 scripts]# sh test.sh "i love" linux and python.
i love linux and python.
------------
i love
linux
and
python.
# 可以看出 "$*"输出结果是 "$1 $2 $3 ... $n"
# 而"$@" 输出结果是 "$1" "#2" "$3" ... "$n"
shell变量字串知识及实践
表达式 | 说明 |
---|---|
${parameter} | 返回变量$parametert的内容 |
${#parameter} | 返回变量$parameter内容的长度(按字符),也适合特殊变量 |
${parameter:offset} | 在变量${parameter}中,从位置offset之后开始提取子串到结尾 |
${parameter:offset:length} | 在变量${parameter}中,从位置offset之后开始提取长度未length的子串 |
${parameter#word} | 从变量${parameter}开头 开始删除最短 匹配的word子串 |
${parameter##word} | 从变量${parameter}开头 开始删除最长 匹配的word子串 |
${parameter%word} | 从变量${parameter}结尾 开始删除最短 匹配的word子串 |
${parameter%%word} | 从变量${parameter}结尾 开始删除最长 匹配的word子串 |
${parameter/pattern/string} | 使用string代替第一个匹配的pattern |
${parameter//pattern/string} | 使用string代替所有匹配的pattern |
变量内容"子串"的删除和替换(重点)
====内容的删除====
[root@m01 ~]# url=www.sina.com.cn
1.${parameter}案例:获取变量内容
[root@m01 ~]# echo ${url}
www.sina.com.cn
2.${#parameter}案例:获取变量值的长度
[root@m01 ~]# echo ${#url}
15
====索引切片====
3.${parameter:offset}案例:在变量${parameter}中,从位置offset之后开始提取子串到结尾
[root@m01 ~]# echo ${url:2}
w.sina.com.cn
[root@m01 ~]# echo ${url:3}
.sina.com.cn
4.${parameter:offset:length}案例:从变量${parameter}中从位置offset之后开始提取长度未length的子串
[root@m01 ~]# echo ${url:3:4}
.sin
[root@m01 ~]# echo ${url:1:3}
ww.
5.${parameter#word}案例:从变量${parameter}开头删除最短匹配的word子串
[root@m01 ~]# echo ${url#*.}
sina.com.cn
[root@m01 ~]# echo ${url#*c}
om.cn
6.${parameter##word}案例:${parameter}开头删除最长匹配的word子串
[root@m01 ~]# echo ${url##*.}
cn
[root@m01 ~]# echo ${url##*c}
n
#发现没有删除内容,是因为从前往后,a.之前还有内容,写法错误,所以无法删除
[root@m1 ~]$ echo ${url#a.}
www.sina.com.cn
[root@m1 ~]$ echo ${url#*a.} 这样写就可以了
com.cn
7.${parameter%word}案例:从变量${parameter}`结尾`开始删除`最短`匹配的word子串
[root@m01 ~]# echo ${url%cn}
www.sina.com.
[root@m01 ~]# echo ${url%.*}
www.sina.com
[root@m01 ~]# echo ${url%m.cn}
www.sina.co
8.${parameter%%word}案例:从变量${parameter}`结尾`开始删除`最长`匹配的word子串
[root@m01 ~]# echo ${url%%.*}
www
对比
[root@m01 ~]# a=tianyun.1000phone.com
[root@m01 ~]# echo ${a%.*} #匹配最短
tianyun.1000phone
[root@m01 ~]# echo ${a%%.*} #匹配最长
tianyun
===变量替换===
9.${parameter/pattern/string}案例:使用string代替第一个匹配的pattern
[root@m01 ~]# echo ${url/n/N}
www.siNa.com.cn
[root@m01 ~]# echo ${url/w/W}
Www.sina.com.cn
10.${parameter//pattern/string}案例:使用string代替所有匹配的pattern
[root@m01 ~]# echo ${url//n/N}
www.siNa.com.cN
[root@m01 ~]# echo ${url//w/W}
WWW.sina.com.cn
shell特殊变量扩展知识
${parameter:-word}
如果parameter变量值为空或未赋值,就返回word字符串替代变量的值。冒号是可以省略的。
用途:如果变量为定义,则返回备用值,防止变量为空值或未定义而导致异常。
例:
[root@m01 ~]# result=${test:-test1}
[root@m01 ~]# echo $test
[root@m01 ~]# echo $result
test1
[root@m01 ~]# echo $test
[root@m01 ~]#
#以上说明短横线的作用:当变量值为空时,短横线后面的值会赋值给变量,当不为空时,不能覆盖原来的值
${变量名-新的变量名}
变量没有被赋值:会使用“新的变量值”替代
变量有被赋值(包括空值):不会被替代
企业应用:防止变量为空从根删起--造成误删
find ${path:-/tmp} -name "*.log" -mtime +7|xargs rm -f
[root@m01 ~]# find ${path:-/tmp} -name "*.log"
/tmp/glances.log
[root@m01 ~]# path=/opt
[root@m01 ~]# find ${path:-/tmp} -name "*.log"
[root@m01 ~]# touch /opt/c.log
[root@m01 ~]# find ${path:-/tmp} -name "*.log"
/opt/c.log
${parameter:=word}
如果parameter变量值为空或未赋值,就设置这个变量值为word,并返回其值。位置变量和特殊变量不适用。
用途:基本同上一个${parameter:-word} ,但是又额外给parameter变量赋值了。
例:
[root@m01 ~]# echo $test
[root@m01 ~]# result=${test:=test1}
[root@m01 ~]# echo $result
test1
[root@m01 ~]# echo $test
test1
#当test值为空,test1的值不但会赋值给test还会赋值给result.
${parameter:?word} 如果parameter变量值为空或未赋值,word字符串将被作为标准错误输出,否则输出变量的值。用途:用于捕捉由于变量未定义而导致的错误,并退出程序。
例如:
[root@m01 ~]# result=${test2:?变量内容为空}
-bash: test2: 变量内容为空
[root@m01 ~]# test2=xxx
[root@m01 ~]# echo $test2
xxx
[root@m01 ~]# result=${test2:?变量内容为空}
[root@m01 ~]# result=${test2:?变量内容为空}
#如果parameter值为空,就报错,否则就输出变量的值
${parameter:+word}如果parameter变量值为空或未赋值,则什么都不做,否则word字符串替代变量的值。
例如:
[root@m01 ~]# result1=${test3:+heihei}
[root@m01 ~]# echo $result1
[root@m01 ~]# echo $test3
[root@m01 ~]# test3=333
[root@m01 ~]# result1=${test3:+heihei}
[root@m01 ~]# echo $result1
heihei
[root@m01 ~]# echo $test3
333
#意思就是test3值为空时,什么都不做,否则将值赋值给result1
shell进程特殊状态变量
状态变量 | 作用说明 |
---|---|
$? | 获取执行上一个指令的执行状态,返回值为0是成功,非0为失败 |
$$ | 或者当前执行的shell脚本的进程号(PID)。(后面三个,了解即可) |
$! | 获取上一个在后台工作的进程的进程号(PID) |
$__ | 获取在此之前执行的命令或脚本的最后一个参数 |
案例:
[root@m01 ~]# pwd
/root
[root@m01 ~]# echo $?
0
[root@m01 ~]# pww
-bash: pww: command not found
[root@m01 ~]# echo $?
127
shell变量的数值计算实践
expr命令
expr是一款便打算计算工具,使用它完成表达式的求值操作
expr的常用运算:加减乘除,求模也就是取余运算%。
更多用法参考:man expr
1.在shell编程中,常用来判断一个数是否为整数。
[root@m01 scripts]# cat test2.sh
#!/bin/bash
expr 2 + $1 &>/dev/null
if [ $? -eq 0 ]
then
echo "$1 is integer"
else
echo "$1 is noninteger"
fi
[root@m01 scripts]# sh test2.sh 1
1 is integer
[root@m01 scripts]# sh test2.sh 1.1
1.1 is noninteger
2.通过expr判断文件扩展名
[root@m01 scripts]# cat expr1.sh
#!/bin/bash
expr "$1" : ".*\.txt" &>/dev/null
if [ $? -eq 0 ]
then
echo "$1 是文本"
else
echo "$1 不是文本"
fi
[root@m01 scripts]# sh expr1.sh hh.txt
hh.txt 是文本
[root@m01 scripts]# sh expr1.sh hh.html
hh.html 不是文本
3.通过expr计算字符串的长度
[root@m01 scripts]# char="I love linux and python"
[root@m01 scripts]# expr length "$char"
23
其他计算字符串长度的方法:
[root@m01 scripts]# echo ${#char}
23
[root@m01 scripts]# echo ${char} |wc -L
23
# -L 打印最长行的长度
[root@m01 scripts]# echo ${char} |awk '{print length(($0))}'
23
[root@m01 scripts]# echo ${char} |awk '{print length}'
23
算数运算
算数运算符 | 意义 |
---|---|
+ - | 加法或正号;减法或负号 |
* / % | 乘法;除法;取余(取模) |
** | 幂运算 |
++ – | 增加及减少,可以前置也可以放在变量结尾,默认步长为1 |
! && || | 逻辑非(取反);逻辑与(and);逻辑或(or) |
< <= > >= | 比较符号,小于,小于等于,大于,大于等于 |
== != = | 比较符号,相等,不相等,对于字符串"="也可以表示相等 |
<< >> | 向左位移,向右位移 |
~ | & ^ | 按位取反;按位异或;按位与;按位或 |
= += -= *= /= %= | 赋值运算,例如a+=1等同a=a+1,a-=1等同a=a-1 |
bash编程常见运算命令汇总
运算操作符与运算命令 | 解释 |
---|---|
(()) | 用于整数运算的常用运算符,效率很高 |
let | 用于整数运算,类似(()) |
expr | 可以用于整数运算,还有其他的额外功能,如判断是否为整数 |
bc | Linux下的一个计算器程序(适合整数以及小数运算) |
$[] | 用于整数运算 |
awk | 即可用于整数运算,也可以用于小数运算 |
declare | 定义变量值和属性,-参数可以用于定义整形变量,做运算 |
案例:
(())
[root@m01 scripts]# c=$((2*3))
[root@m01 scripts]# echo $c
6
[root@m01 scripts]# echo $((1+2*3-4/2))
5
let
[root@m01 scripts]# let i=2+2
[root@m01 scripts]# echo $i
4
expr
[root@m01 scripts]# expr 2 + 2
4
[root@m01 scripts]# expr2 + 2
-bash: expr2: command not found
[root@m01 scripts]# expr 2+ 2
expr: syntax error
[root@m01 scripts]# expr 2 +2
expr: syntax error
#前后必须有空格,使用称号时需要加反斜线,拼特定含义
$[]
[root@m01 scripts]# echo $[2+2]
4
bc
[root@m01 scripts]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
5.5-1.2
4.3
[root@m01 scripts]# echo 1.2*3|bc
3.6
awk
[root@m01 scripts]# echo 1.1 0.9 |awk '{print $1 - $2}'
0.2
[root@m01 scripts]# echo 3.3 1.1 |awk '{print $1 / $2}'
3
[root@m01 scripts]# echo 3.3 1 |awk '{print $1 / $2}'
3.3
特殊内置命令read
从键盘读取变量值,通常在shell脚本中与用户交互的场合使用。该命令可以一次性读取多个变量的值,变量和输入的值都需要使用空格隔开。在read命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量REPLY。
参数:
-p 指定读取值时的提示符
-t 指定读取值时等待的时间,默认单位秒
-s 不回显
-n 输入字符个数
案例:
[root@m01 scripts]# read -t 5 -p "请输入一个数值:" a
请输入一个数值:20
[root@m01 scripts]# echo $a
20
shell案例
通过read方式读入整数变量,计算两个数的加减乘除幂模运算
[root@m01 scripts]# cat read.sh
#!/bin/bash
read -p "请输入两个整数:" a b
echo "a+b=$(($a+$b))"
echo "a+b=$(($a-$b))"
echo "a+b=$(($a*$b))"
echo "a+b=$(($a/$b))"
echo "a+b=$(($a**$b))"
echo "a+b=$(($a%$b))"
[root@m01 scripts]# sh read.sh
请输入两个整数:2 2
a+b=4
a+b=0
a+b=4
a+b=1
a+b=4
a+b=0
也可以通过传参的方式
[root@m01 scripts]# cat read1.sh
#!/bin/bash
a=$1
b=$2
echo "a+b=$(($a+$b))"
echo "a+b=$(($a-$b))"
echo "a+b=$(($a*$b))"
echo "a+b=$(($a/$b))"
echo "a+b=$(($a**$b))"
echo "a+b=$(($a%$b))"
[root@m01 scripts]# sh read1.sh 2 2
a+b=4
a+b=0
a+b=4
a+b=1
a+b=4
a+b=0
扩展1
[root@m01 scripts]# cat read.sh
#!/bin/bash
read -p "请输入两个整数:" a b c
if [ -z $a ]
then
echo "error1:必须是两个整数"
exit
elif [ -z $b ]
then
echo "error2:必须是两个整数"
exit
fi
if [ -z $c ]
then
expr $a + $b + 3 &>/dev/null
if [ $? -eq 0 ]
then
echo "a+b=$(($a+$b))"
echo "a+b=$(($a-$b))"
echo "a+b=$(($a*$b))"
echo "a+b=$(($a/$b))"
echo "a+b=$(($a**$b))"
echo "a+b=$(($a%$b))"
else
echo "输入的不是整数"
exit
fi
else
echo "error3:必须是两个整数"
fi
[root@m01 scripts]# sh read.sh
请输入两个整数:1 2
a+b=3
a+b=-1
a+b=2
a+b=0
a+b=1
a+b=1
[root@m01 scripts]# sh read.sh
请输入两个整数:w 1
输入的不是整数
[root@m01 scripts]# sh read.sh
请输入两个整数:2 e
输入的不是整数
[root@m01 scripts]# sh read.sh
请输入两个整数:33 3 3
error3:必须是两个整数
[root@m01 scripts]# sh read.sh
请输入两个整数:1 2 3 4
read.sh: line 13: [: 3: binary operator expected
error3:必须是两个整数
[root@m01 scripts]# sh read.sh
请输入两个整数:1 1.1
输入的不是整数
# 当脚本较为繁杂时,就不适合使用read,但是read和用户交互性较好。
扩展2,使用传参的方式
[root@m01 scripts]# cat test.sh
#!/bin/bash
a=$1
b=$2
if [ $# -ne 2 ]
then
echo "只能输出两个整数"
exit 1
else
expr $a + $b + 3 &>/dev/null
if [ $? -eq 0 ]
then
echo "a+b=$(($a+$b))"
echo "a+b=$(($a-$b))"
echo "a+b=$(($a*$b))"
echo "a+b=$(($a/$b))"
echo "a+b=$(($a**$b))"
echo "a+b=$(($a%$b))"
else
echo "输入的不是整数"
exit 2
fi
fi
[root@m01 scripts]# sh test.sh 1 2
a+b=3
a+b=-1
a+b=2
a+b=0
a+b=1
a+b=1
[root@m01 scripts]# sh test.sh 1 2 3
只能输出两个整数
[root@m01 scripts]# sh test.sh w 2 3
只能输出两个整数
[root@m01 scripts]# sh test.sh 1 w 3
只能输出两个整数
[root@m01 scripts]# sh test.sh 1 2 e
只能输出两个整数
[root@m01 scripts]# sh test.sh 1.1 2
输入的不是整数
关于cat<<EOF的使用方法
cat<<EOF是从标准输入设备(一般为键盘)获取输入,在第二个EOF处结束输入,同时输出到输出设备(一般为显示器)。
例如:
[root@m01 scripts]#
[root@m01 scripts]# cat <<EOF
> This is test file!
> EOF
This is test file!
#结束的EOF必须是行首,否则被视为标准输入而不是结束分解符。
shell脚本的条件测试与比较
通常,在bash的各种条件结构和流程控制中都要进行各种测试,然后根据测试结果执行不同的操作,有时也会与if等条件语句相结合,来完成测试判断,减少程序运行的错误,执行测试条件表达式后通常会返回真或假,就像执行命令后的返回值为0和非0表示真假一样。
test命令
执行条件表达式
参数:
文件操作符
常用:
-a FILE 如果文件存在,则为true
-d FILE 如果文件是目录,则为true
-e FILE 如果文件存在,则为true
-f FILE 如果文件存在且为普通文件,则为true
-L FILE 如果文件是链接文件,则为true
-r FILE 如果文件可以读取,则为true
-s FILE 如果文件存在且不为空(大小不为0),则为true
-w FILE 如果文件可写,则为true
-x FILE 如果文件可以执行,则为true
常用字符串运算符:
-z STRING 如果字符串为空,则为true
-n STRING 如果字符串不为空,则为true
STRING 如果字符串不为空,则为true
STRING1 = STRINFG2 如果字符串相等,则为true
STRING != STRING2 如果字符串不相等,则为true
文件比较:
FILE1 -nt FILE2 根据修改日期,如果file1 比 file2 新,则为true
FILE1 -ot FILE2 根据修改日期,如果file1 比 file2 旧,则为true
FILE1 -ef FILE2 如果file1 为 file2的硬连接,则为true
返回值:如果表达式执行结果为成功时返回0,当表达式执行结果为失败或给出非法参数时返回1。
其他了解即可:
可参考:https://wangchujiang.com/linux-command/c/test.html
或者其他参考man 手册
案例:
[root@m01 scripts]# test -a /etc/passwd
[root@m01 scripts]# echo $?
0
[root@m01 scripts]# test -a /etc/passddd
[root@m01 scripts]# echo $?
1
六种条件测试语法
条件测试语法 | 说明 |
---|---|
test <测试表达式> | test命令和 "<测试表达式>"之间至少有一个空格 |
[ <测试表达式> ] | 单中括号边界和内容至少有一个空格 |
[[ <测试表达式> ]] | 双中括号边界和内容之间至少有一个空格,比[]更新的语法格式;推荐使用 |
((<测试表达式>)) | 双小括号一般用于if语句中,双小括号两端不需要有空格 |
(<测试表达式>) | 小括号应用较少,了解即可 |
`<测试表达式>``` | 通过反引号实现测试条件表达式,应用较少,了解即可 |
案例:
[root@m01 scripts]# [ -e /etc/passwd ] && echo 1 || echo 0
1
[root@m01 scripts]# [ -e /etc/psss ] && echo 1 || echo 0
0
[root@m01 scripts]# [[ 1 -ne 2 ]] && echo 1 || echo 0
1
[root@m01 scripts]# [[ 2 -ne 2 ]] && echo 1 || echo 0
0
条件表达式的编程语法
[ <测试表达式> ] && 命令
如果前面的表达式成立,那么就执行后面的命令
[ <测试表达式> ] || 命令
如果前面的表达式不成立,那么就执行后面的命令
[ <测试表达式> ] && {
命令1
命令2
命令3
}
如果前面的表达式成立,那么就执行后面的命令
[ <测试表达式> ] && 命令1 ||命令2
如果前面的表达式成立,那么就执行命令1,否则就执行命令2
[ <测试表达式> ] && {
命令1
命令2
} || {
命令3
命令4
}
如果表达式成立,那么就执行命令1,2否则执行命令3,4
整数测试表达式
在[]以及test中使用的比较符号 | 在(())和[[]]中使用的比较符号 | 说明 |
---|---|---|
-eq | ==或= | 相等全拼equal |
-ne | != | 不相等全拼not equal |
-gt | > | 大于 greater than |
-ge | >= | 大于等于,greater equal |
-lt | < | 小于,less than |
-le | <= | 小于等于,less equal |
逻辑测试表达式
在[]和test中使用操作符 | 在[[]]和(())使用操作符 | 说明 |
---|---|---|
-a | && | and,与,两端都为真则真 |
-o | || | or,或,两端有一个为真则真 |
! | ! | not 非,相反则为真 |
条件表达式符号的语法对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ielgGMYT-1614393493074)(https://i.loli.net/2021/02/20/hyTE6tzMZdkFWln.png)]
vim编程环境配置
[root@m01 ~]# pwd
/root
[root@m01 ~]# cat .vimrc
set nocompatible
set history=100
filetype on
filetype plugin on
filetype indent on
set autoread
set mouse=c
syntax enable
set cursorline
hi cursorline guibg=#00ff00
hi CursorColumn guibg=#00ff00
set foldenable
set foldmethod=manual
set foldcolumn=0
setlocal foldlevel=3
set foldclose=all
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set smarttab
set ai
set si
set wrap
set sw=4
set wildmenu
set ruler
set cmdheight=1
set lz
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set magic
set noerrorbells
set novisualbell
set showmatch
set mat=4
set hlsearch
set ignorecase
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
set smartindent
set cin
set showmatch
set guioptions-=T
set guioptions-=m
set vb t_vb=
set laststatus=4
set pastetoggle=<F9>
set background=dark
set t_ti= t_te=
highlight Search ctermbg=black ctermfg=white guifg=white guibg=black
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1, "#!/bin/bash")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: daveorff")
call setline(6, "# Organization:")
call setline(7, "# Created Time : ".strftime("%F %T"))
call setline(8, "# Description:")
call setline(9, "##############################################################")
endif
endfunc
shell脚本调试之sh命令
shell命令解释器
参数:
-c string 命令从-c后的字符串读取
-i 实现脚本交互
-n 进行shell脚本的语法检查
-x 实现shell脚本的逐条语句的跟踪
应用
sh -n filename.sh 仅调试
sh -vx filename.sh 以调试的方式执行,查询整个执行过程
使用-x参数跟踪脚本调试shell脚本,能打印除所执行的每一行命令以及当前状态
if结构条件语句知识与实践
简单理解:如果…那么…否则…
单分支
if <条件表达式>
then
指令
fi
双分支
if <条件表达式>
then
指令
else
指令2
fi
多分支
if条件多分枝结构主体为 "如果...,那么...,否则如果,那么,否则如果...那么...,...,否则..."
if <条件表达式1>
then
指令1
elif <条件表达式2>
then
指令2
elif <条件表达式3>
then
指令3
else
指令4
fi
嵌套if
if <条件表达式1>
then
指令1
else
指令2
if <条件表达式2>
then
指令3
fi
fi
逻辑不清晰,不推荐使用,可以使用多个if分支。
实践
例1:如果不存在/backop目录就创建,存在则打印exist
[root@m01 scripts]# vim 01_01.sh
#!/bin/bash
path="/backup"
if [[ -d $path ]]
then
echo "eixst"
else
mkdir $path -p
fi
执行
[root@m01 scripts]# sh 01_01.sh
[root@m01 scripts]# sh 01_01.sh
eixst
案例2:开发shell脚本判断系统剩余内存的大小,如果低于100MB就提示内存不足,否则提示内存充足
分析:先取内存
[root@m01 ~]# free -m
total used free shared buff/cache available
Mem: 3773 124 3488 11 160 3429
Swap: 1999 0 1999
字段结束:
total 内存总数
used 已经使用的内数
free 空闲的内存数
shared 是指共享的
buffes 是指缓冲内存数
cached 是指缓存内存数,单位是kb
关系:total=used+free
使用awk取值
[root@m01 ~]# free -m | awk 'NR==2{print $4}'
3475
再写if语句
[root@m01 scripts]# vim 02.sh
#!/bin/bash
mem=`free -m | awk 'NR==2{print $4}'`
if [[ $mem -le 100 ]]
then
echo "内存不足"
else
echo "内存充足"
fi
#测试
[root@m01 scripts]# sh 02.sh
内存充足
[root@m01 scripts]# sh 02.sh
内存充足
#改到4000测试
[root@m01 scripts]# sh 02.sh
内存不足
案例3:
分别使用变量定义,read读入及脚本传参方式实现比较两个整数的大小
1.read读入方式:
解析:可以在传入的时候设置3个参数,以达到判断是否多出两个整数的目的
先使用rend读入两个整数 read -p "请读入两个整数:" a b c
判断输入整数个数是否小于2 方法:判断b是否为空 只有不为空继续下一步,否则退出
判断输入整数个数是否大于2,判断c是否为空,只有为空才进行下一步,否则退出
如果是再判断是否是两个整数 :如果两个数都是整数则进行下一步,否则退出
expr $a + $b + 3 &>/dev/null
如果都满足则比较大小
[root@m01 scripts]# cat 03_01.sh
#!/bin/bash
read -p "请输入两个整数:" a b c
if [[ -z $b ]]
then
echo "缺失一个数,请输入两个整数"
exit 1
fi
if [[ -n $c ]]
then
echo "参数个数大于2,请输入两个整数"
exit 2
fi
expr $a + $b + 1 &>/dev/null
if [[ $? -ne 0 ]]
then
echo "只能比较整数"
exit 3
fi
if [[ $a -lt $b ]]
then
echo "$a < $b"
elif [[ $a -gt $b ]]
then
echo "$a > $b"
else
echo "$a = $b"
fi
使用传参的方式:
[root@m01 scripts]# cat 03_02.sh
#!/bin/bash
a=$1
b=$2
if [[ $# -ne 2 ]]
then
echo "参数个数不对,请输入两个整数"
exit 1
fi
expr $a + $b + 3 &>/dev/null
if [[ $? -ne 0 ]]
then
echo "只能比较整数"
exit 2
fi
if [[ $a -lt $b ]]
then
echo "$a < $b"
elif [[ $a -gt $b ]]
then
echo "$a > $b"
else
echo "$a = $b"
fi
案例4:
打印一个菜单如下,当用户选择对应的数字时,就执行对应项目的应用
1.install lamp
2.install lnmp
3.exit
[root@m01 scripts]# cat 04.sh
#!/bin/bash
cat<<EOF
1.install lamp
2.install lnmp
3.exit
EOF
read -p "请选择序号1|2|3:" num
expr $num + 2 &>/dev/null
if [[ $? -ne 0 ]]
then
echo "error1:请输入整数"
exit
fi
if [[ $num -eq 1 ]]
then
echo "install lamp..."
elif [[ $num -eq 2 ]]
then
echo "instahll lnmp..."
elif [[ $num -eq 3 ]]
then
echo "exit"
exit
else
echo "请选择序号1~3"
fi
嵌套if写法:
[root@m01 scripts]# cat 04_01.sh
#!/bin/bash
cat<<EOF
1.install lamp
2.install lnmp
3.exit
EOF
read -p "请选择序号1|2|3:" num
expr $num + 2 &>/dev/null
if [[ $? -ne 0 ]]
then
echo "error1:请输入整数"
exit
else
if [[ $num -eq 1 ]]
then
echo "install lamp..."
elif [[ $num -eq 2 ]]
then
echo "instahll lnmp..."
elif [[ $num -eq 3 ]]
then
echo "exit"
exit
else
echo "请选择序号1~3"
fi
fi
shell函数的概念与作用及语法介绍
函数的概念与作用
简单来说,函数的作用就是将程序多次被调用的相同代码组合成函数体,并且为其取名,即函数名。当其他所有重复调用这部分代码的地方只需要用这个名字即可,当需要修改这部分重复代码时,也只需要改变函数体内的一部分代码即可实现所有调用的修改,也可以把函数单独的写入文件中,当需要调用函数时,再加载来使用。
使用shell函数的优势
- 把相同的程序段定义成函数,可以减少整个程序的代码里,提升开发效率
- 增加函数的可读性,易读性,提升管理效率
- 可以实现程序功能模块化,使得程序具备通用性,也就是可移植性
- 对应shell来说,Linux系统里近2000个命令都可以说是shell函数
**函数的多种语法 **
第一种语法:
function 函数名() {
指令集...
return n
}
第二种语法:
function 函数名 {
指令集
return n
}
第三种语法:(推荐)
函数名() {
指令集...
return n
}
注意空格,return 函数返回值
函数的执行
不带参数的函数执行时,直接输入函数名即可(注意不带小括号)。(–简单函数执行)
案例:
[root@m01 scripts]# vim func1.sh
#!/bin/bash
function test_1() {
echo "i am function_t1"
}
function test_2 {
echo "hello t2"
}
test_3() {
echo "hei t3"
}
test_1
test_2
test_3
总结:;定义完函数后,直接使用其名字即可调用。
有关函数执行的重要说明
--执行shell函数时,函数名前的function和函数的小括号都不要带
--函数的定必须在执行前面定义或加载
--shell执行系统中各种程序的顺序为:系统别名-> 函数->系统命令->可执行文件
--函数执行时,会和调用它的脚本共用变量(相当于脚本的参数与函数共用),也可以为函数设定局部变量以及特殊位置参数
--在shell函数中,return命令功能与exit类似,作用是从函数中退出并返回函数值,而exit是退出脚本文件
--return语句会返回有关退出值(即返回值)给调用函数的当前程序,而exit会返回有关退出值(即返回值)给执行程序当前shell
--如果函数存放在单独的文件中,被脚本加载使用时,需要source或 . 点来加载
--在函数内一般使用local定义局部变量,这些变量离开函数即消失,不用local可以在脚本外调用。
**带参数的函数的执行方法格式如下: ** (–函数传参)
[root@m01 scripts]# cat func2.sh
#!/bin/bash
function test_1() {
echo "i am $1"
}
function test_2 {
echo "$2"
}
test_3() {
echo "$3"
}
test_1 我是函数传参1
test_2 4 5 6
test_3 7 8 9
[root@m01 scripts]# sh func2.sh
i am 我是函数传参1
5
9
带参数的函数执行格式:
函数 参数1 参数2 ...
函数后接的参数说明
shell位置参数($1,$2,$3,...$#,$*,$?以及$@等)都可以作为函数的参数使用
此时父脚本的参数临时的被函数所掩盖或隐蔽
$0比较页数,它仍然是父脚本的名称
当函数执行完成时,原来的命令脚本参数即恢复
函数参数变量是函数体里面定义的
#理解:
#比如$?的使用;可以查看函数的执行状态,状态码范围是0-255,且$?取值是脚本的最后一条命令的状态码
[root@m01 scripts]# cat func3.sh
#!/bin/bash
function gg {
echo "hello gg"
return 110
}
gg
[root@m01 scripts]# sh func3.sh
hello gg
[root@m01 scripts]# echo $?
110
#local的使用;
[root@m01 scripts]# cat func4.sh
#!/bin/bash
function test_1 {
local i="xiaoming"
echo "i am $i"
}
test_1
echo $i
[root@m01 scripts]# sh func4.sh
i am xiaoming
#从此输出为空,在函数内一般使用local定义局部变量,这些变量离开函数后即消失
[root@m01 scripts]#
#总结:
#使用local后在函数之外是无法调用函数体内的变量,把local去掉就是脚本变量是可以生效的。
#建议多个函数间定义同一个变量时使用local,这样多个函数间的同名变量便不会发生冲突。
将函数传参转为脚本传参 (–脚本传参)
[root@m01 scripts]# cat func6.sh
#!/bin/bash
daveff() {
echo "i am $1"
}
daveff $1
[root@m01 scripts]# sh func6.sh superman
i am superman
将函数体和函数执行分成不同的文件
1.将函数写入系统函数,/etc/init.d/functions 写入此文件最后两行上面
例:
...
fi
fi
function daveorff() {
echo " I am $1"
}
2.使用点 . 或source调用,地址为 /etc/init.d/functions
[root@m01 scripts]# cat func5.sh
#!/bin/bash
source /etc/init.d/functions
daveorff $1
3.测试,脚本链接什么参数,就输出什么内容
[root@m01 scripts]# sh func5.sh abc
I am abc
[root@m01 scripts]# sh func5.sh cba
I am cba
查看shell /etc/init.d/functios文件中所有的函数名
grep -E "[a-zA-Z]+\(\)" /etc/init.d/functions -o
总结:
函数总共有四种执行方式
1.简单函数与执行
2.带参数的函数编写执行
3.将函数传参转为脚本传参
4.将函数体和函数执行分成不同的文件,详见上文
函数案例
案例:
1.通过脚本传参的方式,检查web网站URL是否正常
解析:
wget命令
--spider 不下载任何大小;模拟爬虫
-q 安静访问 --quiet 安静模式(没有输出)
-o 把记录写的file文件中,加/dev/null表示不输出
-T 超时时间,设定响应超时的秒数
-t 重试,设定最大尝试连接次数(0表示无限制)
[root@m01 ~]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com
[root@m01 ~]# echo $?
0
curl 命令
-l 值显示请求头信息
-s 静默模式,不输出任何东西 -S 显示错误
-o 把输出写到文件,加/dev/null表示不输出
-w % {http_code} 返回状态码,200为正常
-m 设置最大传输时间
[root@m01 ~]# curl www.baidu.com -s &>/dev/null
[root@m01 ~]# echo $?
0
[root@m01 ~]# curl -l -m 5 -s -w "%{http_code}\n" -o /dev/bull www.baidu.com
200
不用函数的的写法
[root@m01 scripts]# cat checkurl.sh
#!/bin/bash
wget --spider -T 5 -q -o /dev/null -t 2 $1
if [[ $? -eq 0 ]]
then
echo "$1 is ok"
else
echo "$1 is fail"
fi
[root@m01 scripts]# sh checkurl.sh www.baidu.com
www.baidu.com is ok
[root@m01 scripts]# sh checkurl.sh www.baidu.co
www.baidu.co is fail
使用函数写法
[root@m01 scripts]# cat checkurl_01.sh
#!/bin/bash
usage(){
echo "Usage: $0 url"
exit 1
}
checkurl(){
wget --spider -T 5 -q -o /dev/null -t 2 $1
if [[ $? -eq 0 ]]
then
echo "is ok"
else
echo "is fail"
fi
}
main(){
if [[ $# -ne 1 ]]
then
usage
fi
checkurl $1
}
main $*
[root@m01 scripts]# sh checkurl_01.sh www.baidu.co
is fail
[root@m01 scripts]# sh checkurl_01.sh www.baidu.com
is ok
case结构条件语句
case结构条件语句相等于多分支的if/elif/else条件语句,但是它比这条件语句看起来更加规范工整,常被用于实现系统服务启动脚本等。
case 语法:
case "变量" in
值1)
指令1...
;;
值2)
指令2...
;;
值3)
指令3...
;;
*)
指令4...
esac
case条件语句的执行流程逻辑图
case条件语句的使用总结
1.case语句和if条件语句的适用性
case语句比较适合变量较少且为固定的数字或字符串集合的情况,而非不确定的的内容,如范围。如果便的值是已知固定的start/stop/restart等元素,那么采用case语句实现比较合适。
2.case语句和if条件语句的常见应用场景
- case主要写服务的启动脚本,一般情况下,传参不同且具有少量的字符串,使用范围较窄
- if就是取值判断,比较,应用比case更广,几乎所有的case语句都可以使用if条件语句实现
3.case语句的特定及优势
case语句就相当于多分支if/elif/else语句,单case语句的优势更规范,易读。
案例:
执行shell脚本,打印一个如下的水果菜单
1.apple
2.pear
3.banana
4.cherry
当用户输入对应的数字选择水果是,告诉他选择的水果是什么,并给水果单词加上一种颜色,使用case语句实现。
[root@m01 scripts]# cat 06.sh
#!/bin/bash
cat << EOF
1.apple
2.pear
3.banana
4.cherry
EOF
read -p "请选择序号:" num
case "$num" in
1)
echo -e "\033[31m apple \033[0m"
;;
2)
echo -e "\033[32m pear \033[0m"
;;
3)
echo -e "\033[33m banana \033[0m"
;;
4)
echo -e "\033[34m cherry \033[0m"
;;
*)
echo -e "\033[36m 请选择1~4 \033[0m"
exit
esac
颜色代码
脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e
格式如下:
echo -e “\033[字背景颜色;文字颜色m字符串\033[0m”
例如:
echo -e “\033[41;36m good \033[0m”
其中41的位置代表底色, 36的位置是代表字的颜色
1、字背景颜色和文字颜色之间是英文的冒号 ";"
2、文字颜色后面有个m
3、字符串前后可以没有空格,如果有的话,输出也是同样有空格
内容的颜色用数字表示,范围为30-37,每个数字代表一种颜色。代码如下:
echo -e "\033[30m 黑色字 \033[0m" #<==30m表示黑色字。
echo -e "\033[31m 红色字 \033[0m" #<==31m表示红色字。
echo -e "\033[32m 绿色字 \033[0m" #<==32m表示绿色字。
echo -e "\033[33m 棕色字 \033[0m" #<==33m表示棕色字(brown),和黄色字相近。
echo -e "\033[34m 蓝色字 \033[0m" #<==34m表示蓝色字。
echo -e "\033[35m 洋红字 \033[0m" #<==35m表示洋红色字(magenta),和紫色字相近。
echo -e "\033[36m 蓝绿色 \033[0m" #<==36m表示蓝绿色字(cyan),和浅蓝色字相近。
echo -e "\033[37m 白色字 \033[0m" #<==37m表示白色字。
给输出的字符串加不同的背景颜色:
字的背景颜色对应的数字范围为40-47,代码如下。
echo -e "\033[40;37m 黑底白字\033[0m" #<==40m表示黑色背景。
echo -e "\033[41;37m 红底白\033[0m" #<==41m表示红色背景。
echo -e "\033[42;37m 绿底白字\033[0m" #<==42m表示绿色背景。
echo -e "\033[43;37m 棕底白字\033[0m" #<==43m表示棕色背景(brown),和黄色背景相近。
echo -e "\033[44;37m 蓝底白字\033[0m" #<==44m表示蓝色背景。
echo -e "\033[45;37m 洋红底白字\033[0m" #<==45m表示洋红色背景(magenta),和紫色背景相近。
echo -e "\033[46;37m 蓝绿底白字\033[0m" #<==46m表示蓝绿色背景(cyan),和浅蓝色背景相近。
echo -e "\033[47;30m 白底黑字\033[0m" #<==47m表示白色背景。
最后面控制选项说明
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m — \33[37m
设置前景色
\033[40m — \33[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\33[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标
;;
3)
echo -e "\033[33m banana \033[0m"
;;
4)
echo -e "\033[34m cherry \033[0m"
;;
*)
echo -e "\033[36m 请选择1~4 \033[0m"
exit
esac
### 颜色代码
脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e
格式如下:
echo -e “\033[字背景颜色;文字颜色m字符串\033[0m”
例如:
echo -e “\033[41;36m good \033[0m”
其中41的位置代表底色, 36的位置是代表字的颜色
1、字背景颜色和文字颜色之间是英文的冒号 “;”
2、文字颜色后面有个m
3、字符串前后可以没有空格,如果有的话,输出也是同样有空格
内容的颜色用数字表示,范围为30-37,每个数字代表一种颜色。代码如下:
echo -e “\033[30m 黑色字 \033[0m” #<==30m表示黑色字。
echo -e “\033[31m 红色字 \033[0m” #<==31m表示红色字。
echo -e “\033[32m 绿色字 \033[0m” #<==32m表示绿色字。
echo -e “\033[33m 棕色字 \033[0m” #<==33m表示棕色字(brown),和黄色字相近。
echo -e “\033[34m 蓝色字 \033[0m” #<==34m表示蓝色字。
echo -e “\033[35m 洋红字 \033[0m” #<==35m表示洋红色字(magenta),和紫色字相近。
echo -e “\033[36m 蓝绿色 \033[0m” #<==36m表示蓝绿色字(cyan),和浅蓝色字相近。
echo -e “\033[37m 白色字 \033[0m” #<==37m表示白色字。
给输出的字符串加不同的背景颜色:
字的背景颜色对应的数字范围为40-47,代码如下。
echo -e “\033[40;37m 黑底白字\033[0m” #<==40m表示黑色背景。
echo -e “\033[41;37m 红底白\033[0m” #<==41m表示红色背景。
echo -e “\033[42;37m 绿底白字\033[0m” #<==42m表示绿色背景。
echo -e “\033[43;37m 棕底白字\033[0m” #<==43m表示棕色背景(brown),和黄色背景相近。
echo -e “\033[44;37m 蓝底白字\033[0m” #<==44m表示蓝色背景。
echo -e “\033[45;37m 洋红底白字\033[0m” #<==45m表示洋红色背景(magenta),和紫色背景相近。
echo -e “\033[46;37m 蓝绿底白字\033[0m” #<==46m表示蓝绿色背景(cyan),和浅蓝色背景相近。
echo -e “\033[47;30m 白底黑字\033[0m” #<==47m表示白色背景。
最后面控制选项说明
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m — \33[37m
设置前景色
\033[40m — \33[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\33[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标