您的位置:首页 > 运维架构 > Shell

shell脚本基础知识(上)

2015-06-25 15:08 696 查看
一、什么是shell
简单点理解,就是系统跟计算机硬件交互时使用的中间介质,它只是系统的一个工具。实际上,在shell和计算机硬件之间还有一层东西那就是系统内核了。打个比方,如果把计算机硬件比作一个人的躯体,而系统内核则是人的大脑,至于shell,把它比作人的五官似乎更加贴切些。回到计算机上来,用户直接面对的不是计算机硬件而是shell,用户把指令告诉shell,然后shell再传输给系统内核,接着内核再去支配计算机硬件去执行各种操作。
试验环境为linux发布版本(Redhat/CentOS)系统默认安装的shell叫做bash,即Bourne Again Shell,它是sh(Bourne Shell)的增强版本。Bourn Shell 是最早行起来的一个shell,创始人叫Steven Bourne,为了纪念他所以叫做Bourn Shell,检称sh。

二、linux shell中的特殊符号
1、 * :代表零个或多个字符或数字。

2.、 ? :只代表一个任意的字符。3、 # :这个符号在linux中表示注释说明的意思,即”#”后面的内容linux忽略掉。
在命令的开头或者中间插入”#” ,linux都会忽略掉的。这个符号在shell脚本中用的很多。4.、 \ :脱意字符,将后面的特殊符号(例如”\*” )还原为普通字符。5、 | :管道符,它的作用在于将符号前面命令的结果丢给符号后面的命令。这里提到的后面的命令,并不是所有的命令都可以的,一般针对文档操作的命令比较常用,例如cat, less, head, tail, grep, cut, sort, wc, uniq, tee, tr, split, sed, awk等等,其中grep, sed, awk为正则表达式必须掌握的工具。6、 $ :除了用于变量前面的标识符外,还有一个妙用,就是和'!'结合起来使用。‘!$'表示上条命中中最后一个变量(也许称为变量不合适,总之就是上条命令中最后出现的那个东西)。

三、shell脚本结构以及执行方法

1、shell脚本的结构
开头行指定bash路径: #! /bin/bash 、以#开头的行作为解释说明 、脚本的名字以.sh结尾,用于区分这是一个shell脚本。

2、shell脚本的执行方法
[root@hpf-linux shell]# cat test1.sh         //创建第一个脚本
#!/bin/bash
echo "hello world!"
[root@hpf-linux shell]# ll
总用量 4
-rw-r--r-- 1 root root 33 6月  24 08:12 test1.sh
[root@hpf-linux shell]# chmod a+x test1.sh
[root@hpf-linux shell]# ./test1.sh              //第一种执行脚本的方法,记住这种方法要将脚本添加X的权限
hello world!
[root@hpf-linux shell]# /root/shell/test1.sh //或者使用绝对路径,但一定要有X的权限
hello world!
[root@hpf-linux shell]# bash test1.sh     //第二种执行脚本的方法,下面三个与这个类是,但是在写脚本时脚本内最好写绝对路径避免出错
hello world!
[root@hpf-linux shell]# sh  test1.sh
hello world!
[root@hpf-linux shell]# /bin/bash test1.sh
hello world!
[root@hpf-linux shell]# /bin/sh test1.sh
hello world!
[root@hpf-linux shell]# /bin/sh -x test1.sh    //这样可以查看脚本的执行过程,在今后编写脚本出错时可以用这排错
+ echo 'hello world!'
hello world!


四、date命令的简介
1、常用选项及其显示形式
[root@hpf-linux shell]# date +%Y       //%Y显示完整的年份
2015
[root@hpf-linux shell]# date +%y       //%y 年的最后两个数字(1999则是99)
15
[root@hpf-linux shell]# date +%M   //%M  分钟(00~59)
07
[root@hpf-linux shell]# date +%m    //%m 月份(01~12)
06
[root@hpf-linux shell]# date +%d     //%d 一个月的第几天(01~31)
24
[root@hpf-linux shell]# date +%h      //%h  月的简称(Jan~Dec)
6月
[root@hpf-linux shell]# date +%H     //%H  小时,24小时制(00~23)
09

[root@hpf-linux shell]# date +%s     //%s   从1970年1月1日00:00:00到目前经历的秒数
1435108154
[root@hpf-linux shell]# date +%S     //%S   显示秒(00~59)
08
[root@hpf-linux shell]# date +%F     //%F   显示年月日
2015-06-24

[root@hpf-linux shell]# date  +%Y-%m-%d    //和%F表示的一样
2015-06-24
[root@hpf-linux shell]# date +%T     //%T   显示时间,24小时制(hh:mm:ss)
09:24:40
[root@hpf-linux shell]# date  +%H:%M:%S    //和%T表示的一样
10:33:57
[root@hpf-linux shell]# date +%w     //%w 一个星期的第几天(0代表星期天)
3
[root@hpf-linux shell]# date +%W     //%W 一年的第几个星期(00~53,星期一为第一天)
25
[root@hpf-linux shell]# date +%j      //%j 一年的第几天(001~366)
175
[root@hpf-linux shell]# date +%Z     //%Z   显示时区,日期域(CST)
CST
[root@hpf-linux shell]# date +%a      //%a   星期的简称(Sun~Sat)
三
[root@hpf-linux shell]# date +%A     //%A  星期的全称(Sunday~Saturday)
星期三
[root@hpf-linux shell]# date +%D    //%D 日期(mm/dd/yy)
06/24/15
[root@hpf-linux shell]# date -d @100   //显示从1970年1月1日00:00:00经历100秒的显示
1970年 01月 01日 星期四 08:01:40 CST
[root@hpf-linux shell]# date -d "-1 day" +"%F %T"  //显示一天前的当前时间,同时可以将“-”改为“+”表示一天后的当前时间,也可以把day改为month(月)、year(年)、week(周)、hour(小时)、min(分钟)、sec(秒)。
2015-06-23 23:59:24


五、shell脚本中的变量
1、引用某个命令的结果,使用变量代替
[root@hpf-linux shell]# file=`which vim`    //注意等号左右不能有空格
[root@hpf-linux shell]# echo $file
/usr/bin/vim
[root@hpf-linux shell]# rpm -qf $file
vim-enhanced-7.2.411-1.8.el6.i686
上面三个操作为定义了file这个变量存放的是vim命令的存放路径,然后让rpm命令通过调用file这个变量的内容来查询vim命令的安装包
[root@hpf-linux shell]# rpm -qf `which vim`    //等同于上面的操作结果,但是不是很容易理解,今后在写脚本中经常遇到。
vim-enhanced-7.2.411-1.8.el6.i686
扩展学习:变量file只是在当前shell环境生效,要是进入子shell就无法使用,若要想在子shell也能使用则要在命令行使用export声明为全局变量。但是声明后的变量虽然能在子shell中使用,但是一旦另开立一个终端就无法生效了,若还想在别的终端使用则要把export声明全局变量写到/etc/profile、/etc/bashrc 或者家目录的.bash_profile、.bashrc四个文件的任意一个。在写入后还要记住前两个文件是所有用户都能使用,而后两个只能是家目录所在的用户才能使用。

2、参数的变量:
[root@hpf-linux shell]# cat test3.sh
#!/bin/bash
echo "\$0=$0"
echo "\$1=$1"
echo "\$2=$2"
echo "\$3=$3"
echo "\$#=$#"
[root@hpf-linux shell]# sh test3.sh  movies longls bols cangls
$0=test3.sh
$1=movies
$2=longls
$3=bols
$#=4
通过上例可是发现$0为shell脚本本身,$1为手动输入的第一个参数,$2为手动输入的第二个参数,$3为手动输入的第三个参数,$#为统计一共输入了多少个参数,显示4是由于脚本定义的显示参数的变量就三个,所以第四个参数camgls没有给打印出来。

3、数值运算的方法
[root@hpf-linux shell]# aa=11;bb=22
[root@hpf-linux shell]# cc=$aa+$bb
[root@hpf-linux shell]# echo $cc     //不支持直接运算
11+22
[root@hpf-linux shell]# cc=$(($aa+$bb))
[root@hpf-linux shell]# echo $cc
33
[root@hpf-linux shell]# cc=$[$aa+$bb]
[root@hpf-linux shell]# echo $cc
33
通过上例可以发现在shell环境下做数值运算时直接进行运算会出现不是我们所要的结果,而若要正确使用数值运算则要添加[]或者(())来进行运算才能达到想要的运算结果。

六、shell脚本的逻辑判断if
1、if语句的格式
格式1:if 条件 ; then 语句; fi
格式2:if 条件; then 语句; else 语句; fi
格式3:if …; then … ;elif …; then …; else …; fi

2、if语句逻辑判断表达式
if [ $a -gt $b ] //gt大于
if [ $a -lt 5 ] //lt小于
if [ $b -eq 10 ] //eq等于
对于if语句的判断表达式一定要注意在中括号内的空格,为增加shell的可读性建议在数值运算的表达式用两个小括号(()),若用中括号[]可能会和在逻辑判断表达式一块使用时出错。在shell中很少用<、>、=等运算符号,会使用gt、lt等表示运算符号下面介绍下用字母表示运算符。
大于 > gt (greater than)
小于 < lt (less than)
大于等于 >= ge
小于等于 <= le
等于 == eq(equal)
不等于 != ne

3、 if 判断文件、目录属性
[ -f file ]判断是否是普通文件,且存在
[ -d file ] 判断是否是目录,且存在
[ -e file ] 判断文件或目录是否存在
[ -r file ] 判断文件是否可读
[ -w file ] 判断文件是否可写
[ -x file ] 判断文件是否可执行

4、 if 判断一些特殊用法
在写脚本时会有这样的需求:在执行脚本时由于错误导致变量为空但如果我们没有进行判断处理就会出现未知的错误,所以下面介绍如何用if语句判断变量是否为空。
[root@hpf-linux shell]# n=`wc -l /etc/passwd  |awk  '{print $3}'`
[root@hpf-linux shell]# echo $n

[root@hpf-linux shell]#  if [ -z $n ];then echo "\$n is null";fi
$n is null
[root@hpf-linux ~]#  n=`wc -l /etc/passwd  |awk  '{print $1}'`
[root@hpf-linux ~]# echo $n
31
[root@hpf-linux ~]#  if [ ! -z $n ];then echo "\$n is not null";fi
$n is not null
通过上面的例子说明由于n为空则要在if语句中用-z来判断是否为空,! z用来判断n是否为不空,若有值则输出then后的表达式结果。

5、应用举例
手动输入两个数字并判断两个数字的大小:
[root@hpf-linux shell]# cat test4.sh
#!/bin/bash

read -p "请输入一个数字a= " a
read -p "请输入一个数字b= " b

if   [ $a -eq $b ]
then
echo "a等于b"
elif [ $a -lt $b ]
then
echo "a小于b"
else
echo "a大于b"
fi
[root@hpf-linux shell]# sh test4.sh
请输入一个数字a= 3
请输入一个数字b= 6
a小于b
判断输入的是否为数字,若不是直接退出,若是判断其为奇数还是偶数:
[root@hpf-linux shell]#  cat test5.sh
#!/bin/bash

read -p "请输入数字a= " a
n1=`echo $a |grep -c [^0-9]`              //匹配输入的字符为非数字的行数,如果为1说明不是数字。
if [ $n1 -eq 1 ]
then
echo "你输入的不是数字"
exit 1
fi

n2=$(($a%2))
if [ $n2 -eq 1 ]
then
echo "你输入的是奇数"
else
echo "你输入的是偶数"
fi
[root@hpf-linux shell]# sh  test5.sh
请输入数字a= 45
你输入的是奇数
[root@hpf-linux shell]# sh  test5.sh
请输入数字a= fdgsd
你输入的不是数字


判断在目录内的文件是普通文件还是目录文件:
[root@hpf-linux shell]# cat test6.sh
#!/bin/bash

read -p "请输入文件或者目录名: " a

if [ -f $a ]
then
echo "这是一个普通文件"
elif [ -d $a ]
then
echo  "这是一个目录文件"
else
echo  "这不是普通文件也不是目录文件"
fi
[root@hpf-linux shell]# ll
总用量 28
drwxr-xr-x 2 root root 4096 6月  25 05:20 cangls
-rwxr-xr-x 1 root root   33 6月  24 08:12 test1.sh
-rw-r--r-- 1 root root   64 6月  25 00:28 test2.sh
-rw-r--r-- 1 root root   83 6月  25 00:33 test3.sh
-rw-r--r-- 1 root root  208 6月  25 03:55 test4.sh
-rw-r--r-- 1 root root  253 6月  25 04:18 test5.sh
-rw-r--r-- 1 root root  229 6月  25 05:24 test6.sh
[root@hpf-linux shell]# sh  test6.sh
请输入文件或者目录名: cangls
这是一个目录文件
[root@hpf-linux shell]# sh  test6.sh
请输入文件或者目录名: test1.sh
这是一个普通文件
三个小脚本的总结:
通过上面三个比较简单的脚本让我们大概了解下shell脚本的基本编程思路,其中特别是最后一个例子,我们可以在添加链接文件、套接字文件等的判断,总之在编程上我们还需要多动手实践,虽然上面的例子比较简单但我在自己做时还是会出现少空格,关键字写错,少写关键字的现象,所以在今后我们编程时一定要细心、冷静等良好的编程习惯,这样才能在今后的工作中保持高效^_^。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux shell