Bash Shell 小试牛刀
一、终端打印
[root@cai ~]# echo welcome to bash!
welcome to bash!
[cairui@cai ~]$ echo 'welcome to bash!'
welcome to bash!
[cairui@cai ~]$ echo "welcome to bash\!"
welcome to bash\!
(注意,双引号内不能直接用特殊符号,需要用转义符\)
[cairui@cai ~]$ printf "hello world"
hello world
#!/bin/bash
#filename:printf.sh
printf "%-5s %-10s %-4s\n" no name mark
printf "%-5s %-10s %-4.2f\n" 1 sarath 80.3456
printf "%-5s %-10s %-4.2f\n" 2 james 90.9989
printf "%-5s %-10s %-4.2f\n" 3 jeff 77.564
得到如下结果
[cairui@cai shell]$ sh printf.sh
no name mark
1 sarath 80.35
2 james 91.00
3 jeff 77.56
1.工作原理
%s ,%c,%d和%f都是格式替换符,其所对应的参数可以置于带引号的格式字符串之后。
%-5s指明格式为左对齐且宽度为5的字符串替换,不够的用空格补上。
对于%-4.2f,其中.2指定保留2个小数位。
2.补充内容
(1)在echo中转义换行符
[cairui@cai shell]$ echo -e "1\t2\t3"
1 2 3
(2)打印彩色输出
重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37
打印彩色文本
[cairui@cai shell]$ echo -e "\e[1;31m this is red text \e[0m"
this is red text
设置彩色背景,重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47
二、玩转变量和环境变量
在bash中,每一个变量的值都是字符串。无论你给变量赋值时有没有引号,值都是以字符串形式存在。有一些特殊的变量会被shell环境和操作系统环境用来存储一些特别的值,这类变量就称为环境变量。
Cat /proc/$PID/environ(查看运行时的环境变量)
例子:
[cairui@cai shell]$ pgrep mysql
11029
11313
[cairui@cai shell]$ sudo cat /proc/11313/environ
TERM=xtermOLDPWD=/application/mysqlPATH=/sbin:/usr/sbin:/bin:/usr/bin:/application/mysql/binPWD=/application/mysqlSHLVL=3MYSQL_HOME=/application/mysql_=/usr/bin/nohup
[cairui@cai shell]$ sudo cat /proc/11313/environ |tr '\0' '\n'
TERM=xterm
OLDPWD=/application/mysql
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/application/mysql/bin
PWD=/application/mysql
SHLVL=3
MYSQL_HOME=/application/mysql
_=/usr/bin/nohup
1.实战演练
[cairui@cai shell]$ var=value
[cairui@cai shell]$ echo $var
value
Variable.sh代码如下:
#!/bin/bash
fruit=apple
count=5
echo "we have $count $fruit(s)"
[cairui@cai shell]$ sh variable.sh
we have 5 apple(s)
Export命令就是用来设置环境变量:
[cairui@cai shell]$ echo $PATH
/application/mysql/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/application/xtrabackup/bin:/home/cairui/bin
[cairui@cai shell]$ export PATH="$PATH:/home/cairui"
[cairui@cai shell]$ echo $PATH
/application/mysql/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/application/xtrabackup/bin:/home/cairui/bin:/home/cairui
2.补充内容
length=${#var}
例如:
[cairui@cai shell]$ vai=1234567890
[cairui@cai shell]$ echo ${#vai}
10
三、使用函数添加环境变量
PATH=/usr/bin;/bin
这意味着只要shell需要执行二进制可执行文件时,它会首先查找/usr/bin,然后是/bin
四、使用shell进行数学运算
在bash shell环境中,可以利用let,[],(())执行基本的算术操作。而在进行高级操作时,expr和bc这两个工具也会非常有用。
1.实例
#!/bin/bash
#filename:jia.sh
no1=4;
no2=5;
let result=no1+no2
echo $result
[cairui@cai shell]$ sh jia.sh
9
自加操作
let no1++
自减操作
let no1--
简写形式
let no+=6
let no-=6
它们分别等于let no=no+6和let no=no-6
(2)bc是一个数学高级工具,这个精密计算器包含了大量的选项。
[root@cai ~]# echo "4*8"|bc
32
no=54
result=’echo “$no*1.5”|bc’
echo $result
81.0
l 设定小数精度。下面,参数scale=2将小数位个数设置为2.
[cairui@cai shell]$ echo "scale=2;3/8"|bc
.37
进制转换。用bc可以将一种进制系统转换为另一种。(10进制转换2进制)
#!/bin/bash
#用途:数字转换
no=100
echo "obase=2;$no" |bc
no=1100100
echo "obase=10;ibase=2;$no" |bc
[cairui@cai shell]$ sh shuzizhuanhuan.sh
1100100
100
l 计算平方及平方根
[cairui@cai shell]$ echo "sqrt(100)"|bc
10
[cairui@cai shell]$ echo "10^10"|bc
10000000000
五、玩转文件描述符及重定向
文件描述符是与文件输入、输出相关联的整数。它们用来跟踪已打开的文件。最常见的文件描述符是stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。
0-----stdin
1-----stdout
2-----stderr
1.实例
[cairui@cai shell]$ echo "this is a sample text " >temp.txt
[cairui@cai shell]$ cat temp.txt
this is a sample text
[cairui@cai shell]$ echo "this is a sample text " >>temp.txt
[cairui@cai shell]$ cat temp.txt
this is a sample text
this is a sample text
当命令出现错误时,错误信息就会被打印出来
[cairui@cai shell]$ ls +
ls: cannot access +: No such file or directory(错误信息)
2.工作原理
>等同于1>;对于>>也是等同于1>>
(1)将文件重定向到命令
cmd < file
(2)将脚本内部的文本块进行重定向
#!/bin/bash
cat<<EOF>log.txt
LOG FILE HEADER
this is a test log
function:system statistics
EOF
[cairui@cai shell]$ sh log-txt.sh
[cairui@cai shell]$ cat log.txt
LOG FILE HEADER
this is a test log
function:system statistics
六、数组和关联数组
array_var=(1 2 3 4 5 6)#这些值将会存储在以0为起始索引的连续位置上
另外还可以将数组定义为一组“索引-值”
array_var[0]=”test1”
array_var[1]=”test2”
......
......
......
......
array_var[5]=”test6”
echo $array_var[0]
test1
echo $array_var[*]
test1 test2 test3 test4 test5 test6
打印数组长度
echo ${#array_var[*]}
6
七、使用别名
(1)可以用以下方式创建一个别名
alias new_command=’command sequence’
(2)上述别名只是暂时的。为了使别名永久生效,可以将它放在~/.bashrc文件中
echo ‘alias cmd=”commadn seq”’ >> ~/.bashrc
(3)删除别名,只需要从~/.bashrc中删除就可以了
八、获取终端信息
tput和stty是两款终端处理工具。
1.实例
l 获取终端的行数和列数:
tput cols
tput lines
l 打印当前终端名:
tput longname
l 将光标移动到坐标(100,100)处:
tput cup 100 100
l 设置终端背景色:
tputsetb n
其中,n可以在0到7之间取值
l 设置文本样式为粗体
tput bold
l 设置下划线的起止:
tput smu1
tput rmu1
l 删除从当前光标位置到行尾的所有内容:
tputed
l 在输入密码时,不应该显示输入内容:
#!/bin/bash
#filename:password.sh
echo -e “enter password:”
stty -echo
read password
stty echo
echo
echo password read
九、获取、设置日期和延迟
很多程序要以不同的格式打印日期、设置日期和时间、根据日期和时间执行操作。延时通常用于在程序执行过程中提供一段等待时间(比如1秒)。例如需要在脚本中对某项任务每隔5秒监视一次,就需要知道如何在程序中加入延时。
1.实例
(1)[cairui@cai support-files]$ date
Tue Jun 6 15:27:22 CST 2017
(2)打印纪元时:
[cairui@cai support-files]$ date +%s
1496734094
[cairui@cai support-files]$ date --date "jan 20 2011" +%A
Thursday
(3)用格式串结合+作为date命令的参数:
[cairui@cai support-files]$ date "+%d %b %y"
06 Jun 17
(4)设置时间和日期:
date -s “格式化的日期字符串”
例子:
date -s “21 june 2009 11:01:22”
(5)有时,我们需要检查一组命令所花费的时间,以下代码:
#!/bin/bash
#filename:time_take.sh
start=$(date +%s)
commands;
statements;
end=$(date +%s)
difference=$((end - start))
echo time taken to execute commands is $difference seconds
2.工作原理
日期内容 |
格式 |
星期 |
%a(A) |
月 |
%b(B) |
日 |
%d |
固定格式日期(mm、dd、yy) |
%D |
年 |
%y(Y) |
小时 |
%I或%H |
分钟 |
%M |
秒 |
%S |
纳秒 |
%N |
Unix纪元时(以秒为单位) |
%s |
|
|
3.补充内容
在脚本中推迟执行一段时间,可以用sleep;$sleep no_of_seconds.例如,下面的脚本就使用tput和sleep从0开始计数到40:
#!/bin/bash
#filename:sleep.sh
echo -n Count: (echo -n不换行输出)
tput sc
count=0;
while true;
do
if [ $count -lt 40 ];
then
let count++;
sleep 1;
tput rc
tput ed
echo -n $count;
else exit 0;
fi
done
在上面的例子中,变量count初始化为0,随后每循环一次便加1.echo语句打印出count的值。用tput sc存储光标的位置。在每次循环中,通过恢复之前存储的光标的位置,在终端中打印出新的count的值。恢复光标的命令是tput rc。tput ed清除从当前光标位置到行尾之间的所有内容,使得旧的count值可以被清除并写入新值。循环内的1秒钟延迟是通过sleep命令来实现。
十、调试脚本
(1)bash -x script.sh or sh -x script.sh
(2)使用set -x和set +x对脚本进行部分调试。例如:
#!/bin/bash
#filename:debug.sh
for i in {1..6};
do
set -x
echo $i
set +x
done
echo "script executed"
[cairui@cai shell]$ sh debug.sh
+ echo 1
1
+ set +x
+ echo 2
2
+ set +x
+ echo 3
3
+ set +x
+ echo 4
4
+ set +x
+ echo 5
5
+ set +x
+ echo 6
6
+ set +x
script executed
在上面的脚本中,只会打印出 echo $i的调试信息。因为使用了-x和+x对调试区域进行了限制。
(3)前面两种调试都是内建的。他们通常以固定的格式生成调试信息。但是在很多情况下,我们需要以自定义格式显示调试信息。可以通过传递_DEBUG环境变量来建立这类调试风格。
#!/bin/bash
function DEBUG()
{
[ "$_DEBUG" == "on" ] && $@ || :
}
for i in {1..10}
do
DEBUG echo $i
done
~
[root@cai shell]# _DEBUG=on ./DEBUG.sh
1
2
3
4
5
6
7
8
9
10
我们在每一个需要打印调试信息的语句前加上DEBUG。如果没有把_DEBUG=on传递给脚本,那么调试信息就不会被打印出来。在bash中,命令“:”告诉shell不要进行任何操作。
十一、函数和参数
1.实例
我们可以创建执行特定任务的函数,也可以创建能够接受参数的函数。
(1)定义函数:
function fname()
{
statements;
}
或者
fname()
{
statements;
}
(2)只需要使用函数名就可以调用某个函数:
$fname #执行函数
(3)参数可以传递给函数,并由脚本进行访问:
fname arg1 arg2;#传递函数
以下是函数fname 的定义。在函数fname中,包含了各种访问函数参数的方法。
fname()
{
echo $1,$2;访问参数1和参数2
echo “$@”;以列表的方式一次性打印所有参数
echo “$*”;类似于¥@,但是参数被作为单个实体
return 0;返回值
}
l $1是第一个参数
l $2是第二个参数
l $n是第n个参数
l “$@”被扩展成”$1” “$2” “$3”等
l “$*”被扩展成”$1c$2c$3”,其中c是IFS的第一个字符
l “$@”要比$*用的多。
2.补充内容
(1)递归函数
f() {echo $1;f hello;sleep 1;}
(2)导出函数
export -f fname
十二、不适用回车键来读取n个字符
read是一个重要的bash命令,它用于从键盘或标准输入中读取文本。我们可以使用read以交互的形式读取来自用户的输入,不过read能做的可远远不止于此。任何编程语言的输入库大多都是从键盘读取输入;但只有当回车键按下的时候,才标志着输入完毕。而有些游戏里只需要按q就能释放技能。
(1)下面的语句从输入中读取n个字符并存入变量variable_name;
read -n number_of_chars variable_name
例如:
read -n 2 var
echo $var
(2)用无回显的方式读取密码:
read -s var
(3)显示提示信息:
read -p “enter input:” var
(4)在特定时限内读取输入:
read -t timeout var
read -t 2 var #在2秒内将键入的字符串读入变量var
(5)用特定的定界符作为输入行的结束:
read -d delim_char var
read -d “:” var
hello:#var 被设置为hello
十三、运行命令直至执行成功
在日常工作中使用shell时,有时候命令只有满足某些条件或是某种外部事件(例如文件可以被下载)操作才能成功执行。这种情况下,你可能希望重复执行命令,直到成功为止。
1.实例:
按照以下方式定义函数:
repeat()
{
while true
do
$@ && return
done
}
或者把它放入shell的rc文件,更便于使用:
repeat() {while true;do $@ && return;done}
2.工作原理
我们创建了函数repeat,它包含了一个无限while循环,该循环执行以参数形式(通过$@访问)传入函数的命令。如果命令执行成功,则返回,进而无限循环。
3.补充内容
(1)一种更快的做法
repeat() {while :; do $@ && return; done } 比第一种方法快
(2)增加延时
repeat wget -c ........
repeat() {while :; do $@ && return; sleep 30; done}这使得命令每30秒运行一次。
十四、循环
(1)for循环
for var in list;
do
commands;
done
(2)while循环
while condition
do
commands;
done
(3)until循环
它会一直循环,直到给定的条件为真。
x=0;
until [ $x -eq 9 ];
do
let x++; echo $x;
done
十五、比较与测试
1.实战
(1)if条件
if condition;
then
commands;
fi
(2)else if和else
if condition;
then
commands;
else if condition; then
commands;
else
commands;
fi
(3)算数比较
l 对变量或值进行算数条件判断:
[ $var -eq 0 ] #当$var等于0时,返回真
[ $var -ne 0 ] #当。。。为非0时,返回真
l -gt:大于
l -lt:小于
l -ge:大于或等于
l -le:小于或等于
(4)字符串比较
使用字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误,所以最好避开它们。
l [[$str1=$str2]],相等返回真
l [[$str1==$str2]]检查字符串是否相等的另一种写法
l [[$str1 !=$str2]]如果str1和str2不相同,则返回真
l [[$str1 > $str2]]
l [[$str1 < $str2]]
l [[-z $str1]],如果包含的是空字符串,返回真
l [[-n $str]],如果包含的是非空字符串,则返回真