目录
一、shell script 与shell
shell 和shell script 其实是两个概念,而很多初学者对这两个概念,傻傻分不清楚,甚至一度以为是一个玩意儿。这里再次强调一下,是两个概念,是两个概念,是两个概念,重要的事情说三遍。shell的概念我们在《Linux系统》之深入浅出(三)这篇文章中已经详细的讲过,这里也不再做累述了,如果还不清楚什么是shell,请回头看看那篇文章。
1、什么是shell script
shell script其实就是利用shell里的一个强大功能(程序设计语言)所写的一个程序,这个程序是一个纯文本文件,内含shell的相关语法和指令,搭配正则表达式,管道命令及其数据流重定向等等,来完成一些复杂的管理操作任务。因其使用的是shell功能,并运行在shell环境下,因此不需要编译过程。
shell script 可以看成是一个批处理文件,也可以当成一个程序设计语言。业界内程序员所说的“shell编程",指的就是shell script编程
2、shell script的用途
自动化管理:系统管理员将每天的任务,如查询登录,追踪流量,监控用户使用主机状态,主机的硬件状态,软件更新情况等等,用shell script来自动管理比手动管理更省时省力
追踪和管理系统服务项:CentOS7以前的系统的服务启动接口都是在/etc/init.d这个目录下,这个目录下的所有文件都是script。还有,开机过程也是利用script来搜寻相关设定数据,再传入相关服务的各个参数中的。
管理注册表:可以通过script来检测注册表的动态信息,若发现问题,可以及时的通报给管理员,以加强防火墙的设定,或者是阻挡可疑的IP活动。
指令流水化:某一个作业,可能会涉及到重复的一堆指令,就可以使用script来封装这些指令,做成流水线化。使作业从繁入简。
简单数据处理:script可以进行一些简单的数据处理和逻辑判断
跨平台性:任何类Unix系统都可以运行script。
二、shell编程规范
虽然,shell script是一个纯文本文件,不需要编译,但是,我们在script编程时,仍要遵守相应的规范和注意相关事项。
1、shell script的结构
- 文件的扩展名 必须是.sh
- 文件的首行必须使用#! 指定script的运行shell环境(j脚本解释器)
- # 用于注释
- 指令、选项、参数之间即使有多个空格仍会被视为一个空格。tab键形成的空白也被视为一个空格键
- 空白行会被忽略
2、shell script的执行
执行script的方式有两种,一种是使用bash程序来调用script,一种是直接写script。
使用bash程序来调用:只需要有读(r)权限即可
sh *.sh 或者 bash *.sh
直接写script:*.sh必须要有rx权限才行
绝对路径写法: /home/hyxy/*.sh
相对路径写法: ./*.sh
变量PATH功能: 将*.sh放入~/bin目录下,因为PATH里拼接了~/bin目录。注意:~/bin目录必须自行创建
3、简单示范
示范1:
[michael@master ~]$ cat >test1.sh
#!/bin/bash
ADDR=changchun
echo $ADDR
[michael@master ~]$ sh test1.sh
changchun
示范2:
[michael@master ~]$ cat > test2.sh
#!/bin/bash
mkdir testdir
touch testdir/testfile
[michael@master ~]$ ./test2.sh
bash: ./test2.sh: 权限不够 <== 没有x权限前
[michael@master ~]$ chmod u+x test2.sh <== 赋予x权限
[michael@master ~]$ ./test2.sh
[michael@master ~]$ ll
-rw-rw-r-- 1 michael michael 26 12月 31 18:06 test1.sh
-rwxrw-r-- 1 michael michael 49 12月 31 18:11 test2.sh
drwxrwxr-x 2 michael michael 4096 12月 31 18:12 testdir <==目录
[michael@master ~]$ ll testdir/
-rw-rw-r-- 1 michael michael 0 12月 31 18:12 testfile <==目录里的文件
三、shell字符串
在shell中,最常用的就是字符串了,那么我们来了解一下shell中字符串的使用
1、字符串的基本用法
(1) 字符串不能单独,必须要配合变量。
(2) 字符串可以使用单引号[' '],也可以使用双引号[" "],也可以不用引号
单引号内:
- 单引号内的任何字符没有任何意义,都会原样输出,单引号内使用变量是无效的
- 单引号内不能出现单引号
如:
[michael@master ~] vim test3.sh
var='hello kitty'
echo 'my name is $var' <==单引号内
显示:my name is $var
双引号内:
- 双引号内可以使用变量
- 双引号内可以使用转义字符
如:
[michael@master ~] vim test3.sh
var='hello kitty'
echo “my name is $var” <==双引号内
显示:my name is hello kitty
2、字符串的拼接
在字符串拼接操作时,我们可以进行无缝拼接,或者是在双引号里使用变量
[michael@master ~] vim test3.sh
#!/bin/bash
var1='hello kitty'
var2='welcome to china'
var3=$var1$var2 <==无缝拼接
echo $var3 <== hello kittywelcome to china
var4="my name is $var1" <==在双引号里使用变量
echo $var4 <==my name is hello kitty
再比如环境变量PATH,每一个路径都是用冒号【:】无缝拼接起来的。
3、字符串的长度
可以使用${#variable} 或者 expr length "${variable}"。因为expr是指令,所以别忘记使用反单引号``或者是$()直接看案例:
[michael@master ~] vim test3.sh
#!/bin/bash
var='welcome to china'
length1=${#var}
length2=$(expr length "${var}") <==$()写法
length3=`expr length "$var"` <==反单引号写法
echo $length1 $length2 $length3 <== 16 16 16
4、子字符串的截取
字符串的下标从0开始。而截取有如下写法:
${variable:startIndex} : 从startIndex下标开始,截取到最后
${variable:startIndex:length} : 从startIndex下标开始,截取length个长度
${variable:0-num} : 倒数第num个开始,截取到最后
${variable:0-num:length} : 倒数第num个开始,截取length个长度
[michael@master ~] vim test3.sh
#!/bin/bash
url="http://www.baidu.com"
substr=${url:4}
echo $substr <== ://www.baidu.com
substr=${url:4:4}
echo $substr <== ://w
substr=${url:0-4}
echo $substr <== .com
substr=${url:0-6:4}
echo $substr <== du.c
另外,还可以使用 #、##、%、%%进行删除后保留子串
A、#、## :从左边开始删除。
# :表示从左边删除到第一个指定的字符; 格式: ${variable#关键字符串}
## :表示从左边删除到最后一个指定的字符。 格式: ${variable##关键字符串}
B、%、%% :从右边开始删除。
% :表示从右边删除到第一个指定的字符; 格式: ${variable%关键字符串}
%% :表示从有边删除到最后一个指定的字符。 格式: ${variable%%关键字符串}
另注:删除包括了指定的字符本身。*是通配符,代表0个以上的字符
[michael@master ~]$ vim test3.sh
#!/bin/bash
url="http://www.baidu.com"
substr=${url#*.}
echo $substr <== baidu.com
substr1=${url##*.}
echo $substr1 <== com
url="http://localhost:8080/a.html"
substr=${url%t*}
echo $substr <== http://localhost:8080/a.h
substr1=${url%%:*}
echo $substr1 <== http
5、字符串的替换
格式如下:
${variable/旧字符串/新字符串} :变量内的第一个旧字符串会被新字符串替换掉
${variable//旧字符串/新字符串} :变量内的所有旧字符串会被新字符串替换掉
[michael@master ~]$ vim test3.sh
#!/bin/bash
path=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/hyxy/bin
echo ${path/sbin/xxx}
echo ${path//sbin/xxx}
上面两个echo输出的内容分别为:
[hyxy@master ~]$ sh test3.sh
/usr/local/bin:/usr/bin:/bin:/usr/local/xxx:/usr/sbin:/sbin:/home/hyxy/bin <==第一个sbin被替换
/usr/local/bin:/usr/bin:/bin:/usr/local/xxx:/usr/xxx:/xxx:/home/hyxy/bin <==所有sbin被替换
6、获取子字符串的位置
格式:`expr index "${variable}" substr`
只要匹配到substr中任意一个字符就返回其位置。这个位置序号从1开始
[hyxy@master ~]$ vim test3.sh
#!/bin/bash
url="thisis a good man"
index=`expr index "${url}" si`
echo $index <== 3
url="this is a good man"
index=`expr index "${url}" a`
echo $index <== 9
四、shell数组
1、Array的使用规则
- 在/bin/bash这个shell中,只有一维数组的概念,并且不限定数组的长度。
- 数组的元素下标是从0开始的,
- 获取数组的元素要使用下标
- 下标使用不当,会报错
2、Array的定义
定义格式: variable=(值1 值2 … 值n) 注意:元素之间除了使用空格作为分隔符,还可以使用换行符。
或者
name[0]=值1
name[1]=值2
…
name[n]=值n
3、读取数组
${variable[index]}: 读取index索引上的元素
${variable[*]}或者${variable[@]}:读取所有元素
${#variable[*]}或者${#variable[@]} : 读取数组的长度
[michael@master ~]$ vim test3.sh
#!/bin/bash
citys=(cc sh bj sd hlj)
hobby[0]=book
hobby[1]=film
hobby[2]=music
echo ${citys[0]} <==cc
echo ${hobby[*]} <==book film music
echo ${#hobby[@]} <==3
五、位置参数变量
关于变量的概念、我们已经知晓自定义变量、环境变量、还有一些特殊变量,如$$是返回当前进程的PID,$?是返回上一个指令执行后退出的状态,0表示成功退出。其实,还有一些特殊变量:
$n:n是从0开始的,连续的自然数。
shell在解析用户执行的命令时,会将命令行的一串字符以空格作为分隔符划分成n个部分。按照从左到右的顺序,每个部分依次都有一个固定的变量名$n,从第一部分开始分别为:$0、$1、$2、$3.....。当n大于等于10时,必须使用大括号{}将数字括起来 。
Ex:ls –la file1 file2 file3 ….. file10
$0 的值为:ls -la $0这个变量比较特殊,读取的值为 command + option
$1 的值为file1
…….
${10} 的值为file10
[michael@master ~]$ vim test3.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo ${10}
echo ${11}
[michael@master ~]$ sh test3.sh a b c d e f g h i j k l m n
test3.sh <==$0的值
a <==$1的值
b <==$2的值
j <==$10的值
k <==$11的值
$@: 获取命令后的所有参数,每个值都是独立的
$*:获取命令后的所有参数,合并成一个字符串,中间使用空格分开
$#:获取命令后的参数的个数
-----------------------------------------------如有疑问,敬请留意----------------------------------------------------------