Shell基础
1、Shell概述
Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至编写一些程序。
Shell是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。
Shell的分类:
- Bourne Shell:从1979年起就开始使用Bourne Shell,Bourne Shell的主文件名为sh。
- C Shell:C Shell 主要在BSD版的Unix系统中使用,其语法和C语言相类似而得名
- Shell的两种主要语法类型有Bourne和C,这两种语法彼此不兼容。Bourne家族主要包括:sh、ksh、Bash、psh、zsh;C家族主要包括:csh、tcsh。
- Bash:Bash与sh兼容,Linux使用Bash作为用户的基本Shell。
Linux支持的Shell:/etc/shells
2、Shell脚本的执行方式
2.1、echo输出命令
语法:echo [选项][输出内容]
选项: -e 支持反斜线控制的字符转换
控制字符 | 作用 |
---|---|
\ | 输出\本身 |
\a | 输出警告音 |
\b | 退格键,向左删除键 |
\c | 取消输出行末的换行符,和”-n”选项一致 |
\e | ESCAPE键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车键 |
\t | 制表符,tab键 |
\v | 垂直制表符 |
\Onnn | 按照八进制ASCII码表输出字符,其中0为数字零,nnn是三位八进制数 |
\xhh | 按照十六进制ASCII码表输出字符,其中hh是两位十六进制数 |
# 输出颜色\e[1开始 \e[0m结束
echo -e "\e[1;32m abc \e[0m"
2.2、第一个脚本
#!/bin/bash
# The first program
# Author:aric
echo "hello world"
2.3、脚本执行
- 赋予执行权限,直接运行
- chmod 755 hello.sh
- ./hello.sh
- 通过Bash调用执行脚本
- bash hello.sh
3、Bash的基本功能
3.1、历史命令与命令补全
历史命令:
语法:history [选项][历史命令保存文件]
选项:
-c : 清空历史命令
-w : 把缓存中的历史命令写入历史命令保存文件 ~/.bash_history历史命令默认会保存1000条,可以在环境变量配置文件/etc/profile中进行修改。
历史命令的调用:- 使用上下箭头调用以前的历史命令
- 使用“!n”重复执行第n条历史命令
- 使用“!!”重复执行上一条命令
- 使用“!字符串”重复执行最后一条以该字符串开头的命令
命令补全:在bash中,命令与问价补全是非常方便与常用的功能,只要在输入命令或文件爱你时,按“Tab”键就会自动进行补全。
3.2、命令别名与常用快捷键
1、命令别名:
语法:
shell
alias 别名='原命令' # 设定命令别名
alias # 查询命令别名
命令执行时顺序:
1. 第一顺位执行用绝对路径或相对路径执行的命令。
2. 第二顺位执行别名。
3. 第三顺位执行bash的内部命令。
4. 第四顺位执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令。
删除别名:unalias。
2、常用快捷键:
快捷键 作用 ctrl+A 把光标移动到命令行开头。如果输入的命令过长,想要把光标移动到命令行开头时使用 ctrl+E 把光标移动到命令行结尾 ctrl+C 强制终止当前的命令 ctrl+L 清屏,相当于clear命令 ctrl+U 删除或剪切光标之前的命令,输入一行很长的命令,不用使用退格键一个一个字符的删除,使用该快捷键会更加方便 ctrl+K 删除或剪切光标之后的内容 ctrl+Y 粘贴ctrl+U或ctrl+K剪切的内容 ctrl+R 在历史命令中搜索 ctrl+D 退出当前终端 ctrl+Z 暂停,并放入后台 ctrl+S 暂停屏幕输出 ctrl+Q 恢复屏幕输出
3.3、输入输出重定向
1、标准输入输出:
设备 | 设备文件名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/sdtout | 1 | 标准输出 |
显示器 | /dev/sdterr | 2 | 标准错误输出 |
2、输出重定向:
类型 | 符号 | 作用 |
---|---|---|
标准输出重定向 | 命令 > 文件 | 以覆盖的方式,把命令的正确输出到指定的文件或设备当中 |
标准输出重定向 | 命令 > 文件 | 以追加的方式,把命令的正确输出到指定的文件或设备当中 |
标准错误输出重定向 | 错误命令 2> 文件 | 以覆盖的方式,把命令的错误输出到指定的文件或设备中 |
标准错误输出重定向 | 错误命令 2>> 文件 | 以追加的方式,把命令的错误输出到指定的文件爱你或设备当中 |
正确输出和错误输出同时保存 | 命令 > 文件 2>&1 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 |
正确输出和错误输出同时保存 | 命令 >> 文件 2>&1 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中 |
正确输出和错误输出同时保存 | 命令 &> 文件 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 |
正确输出和错误输出同时保存 | 命令 &>> 文件 | 以追加方式,把正确输出和错误输出都保存到同一个文件当中 |
正确输出和错误输出同时保存 | 命令>>文件1 2 >>文件2 | 把正确的输出追加到文件1中,把错误的输出追加到文件2中 |
3、输入重定向:
语法:wc [选项] [文件名]
选项:
-c 统计字节数
-w 统计单词数
-l 统计行数
命令 < 文件 把文件作为命令的输入
3.4、多命令顺序执行与管道符
1、多命令顺序执行
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 命令1;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1 && 命令2 | 逻辑与;当命令1正确执行则命令2才会执行;当命令1执行不正确,则命令2不会执行 |
dd if=输入文件 of=输出文件 bs=字节数 count=个数
选项:
if=输入文件 指定源文件或源设备
of=输出文件 之地给你目标文件或目标设备
bs=字节数 指定一次输入/输出多少字节,即把这些字节看做一个数据块
count=个数 指定输入/输出多少个数据块
2、管道符
语法:命令1 | 命令2
说明:命令1的正确输出作为命令2的操作对象
命令:grep
作用:在文件中搜索符合条件的内容
语法:
grep [选项] “搜索内容” 文件名
选项:
-i : 忽略大小写
-n : 输出行号
-v : 反向查找
–color=auto 搜索出的关键字用颜色显示
3.5、通配符与其它特殊符号
1、通配符
通配符 | 作用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配0个或任意多个任意字符,也就是可以匹配任何内容 |
[] | 匹配中括号中任意一个字符,例如:[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c。 |
[-] | 匹配中括号中任意一个字符,-代表一个范围。例如:[a-z]代表匹配一个小写字母。 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0-9]代表匹配一个不是数字的字符。 |
2、bash中其它特殊符号
符号 | 作用 |
---|---|
‘’ | 单引号,在单引号中所有的特殊符合,如”$”和“`”都没有特殊含义。 |
“” | 双引号,在双引号中特殊符号都没有特殊含义,但是”$”、“`”和“\”是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。 |
“ | 反引号,反引号括起来的内容是系统命令,在bash中先执行它。和 ()作用一样,推荐使用 {},反引号非常容易看错。 |
${} | 和反引号作用一样,用来引用系统命令。 |
# | 在Shell脚本中,#开头的行代表注释。 |
$ | 用于调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值。 |
\ | 转义符,跟在\之后的特殊符合将失去特殊含义,变为普通字符。如$将输出“$”符合,而不当作是变量引用。 |
4、Bash的变量
变量是计算机内存的单元,其中存放的值可以改变。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。
变量设置规则:
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。
- 在bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型。
- 变量用等号连接值,等号左右两侧不能有空格。
- 变量的值如果有空格,需要使用单引号或双引号包括。
- 在变量的值中,可以使用“\”转义符。
- 如果需要增加变量的值,那么可以进行变量值的叠加。变量需要双引号包含” 变量名"或用 {变量名}包含。
- 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。
- 环境变量名建议大写,便于区分。
变量分类:
- 用户自定义变量
- 环境变量:主要保存的是和系统操作环境相关的数据。
- 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
- 预定义变量:是bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
4.1、用户自定义变量
本地变量:
- 变量定义
- 变量叠加
# 第一种方式
aa="$aa"abc
# 第二种方式
aa=${aa}789
- 变量调用
echo $name
- 变量查看
set
- 变量删除
unset name
4.2、环境变量
用户自定义变量只在当前的Shell中生效,而环境变量会在当前Shell和这个Shell的所有子Shell当中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的Shell中生效。
设置环境变量:
# 声明全局变量
export 变量名=变量值
# 查询变量
env
#删除变量
unset 变量名
系统常见环境变量:
- PATH:系统查找命令的路径
- PATH=”$PATH”:/root/sh ,# PATH变量叠加
- PS1:定义系统提示符的变量
\d: 显示日期,格式为“星期 月 日”
\h: 显示简写主机名。如默认主机名“localhost”
\t: 显示24小时制时间,格式为“HH:MM:SS”
\T: 显示12小时制时间,格式为“HH:MM:SS”
\A: 显示24小时制时间,格式为“HH:MM”
\u: 显示当前用户名
\w: 显示当前所在目录的完整名称
\W: 显示当前所在目录的最后一个目录
#: 执行的第几个命令
$: 提示符,如果是root用户会显示提示符为“#”,如果是普通用户会显示提示符为“$”
4.3、位置参数变量
位置参数变量 | 作用 |
---|---|
$n | n为数字,$0 代表命令本身,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如${10} |
$* | 这个变量代表命令行中所有的参数,$* 把索引的参数看成一个整体 |
$@ | 这个变量也代表命令行中所有的参数,不过$@ 把每个参数区分对待 |
$# | 这个变量代表命令行中所有参数的个数 |
4.4、预定义变量
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态.如果这个变量的值为0,证明上一次命令正确执行;如果这个变量的值为非0,则证明上一个命令执行不正确 |
$$ | 当前进程的进程号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
接收键盘输入
语法:
read [选项] [变量名]
选项: -p “提示信息” : 在等待read输入时,输出提示信息
-t 秒数 : read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数 : read命令只接受指定的字符数,就会执行
-s : 隐藏输入的数据,适用于机密信息的输入
5、Bash的运算符
5.1、数值运算与运算符
declare声明变量类型
语法:
declare [+/-][选项]变量名
选项:
-:给变量设定类型属性
+:取消变量的类型属性
-i:将变量声明为整数型
-x:将变量声明为环境变量
-p:显示指定变量的被声明的类型
数值运算方法一:
aa=1
bb=2
# 给变量aa和bb赋值
declare -i cc=$aa+$bb
方法二:expr或let数值运算工具
aa=1
bb=2
# 给变量aa和变量bb赋值
dd=$(expr $aa + $bb)
# dd的值是aa和bb的和,注意:“+”号左右两侧必须有空格
方法三:“ ((运算符))”或“ [运算式]”
aa=1
bb=2
ff=$(($aa+$bb)
gg=$[$aa+$bb]
优先级 | 运算符 | 说明 |
---|---|---|
13 | - 、 + | 单目负、单目正 |
12 | `! 、 | 逻辑非、按位取反或补码 |
11 | * 、 / 、 % | 乘、除、取模 |
10 | + 、 - | 加、减 |
9 | << 、 >> | 按位左移、按位右移 |
8 | <= 、 >= 、 < 、 > | 小于或等于、大于或等于、小于、大于 |
7 | == 、!= | 等于、不等于 |
6 | & | 按位与 |
5 | ^ | 按位异或 |
4 | | | 按位或 |
3 | && | 逻辑与 |
2 | || | 逻辑或 |
1 | =,+=,-=,*=,/=,%=,&=,^=,<<=,>>=,|= | 赋值,运算且赋值 |
5.2、变量测试与内容替换
变量置换方式 | 变量y没有设置 | 变量y为空值 | 变量y设置值 |
---|---|---|---|
x=${y-新值} | x=新值 | x为空 | x=$y |
x=${y:-新值} | x=新值 | x=新值 | x=$y |
x=${y+新值} | x为空 | x=新值 | x=新值 |
x=${y=新值} | x=新值 y=新值 | x为空 y值不变 | x=$y y值不变 |
x=${y:=新值} | x=新值 y=新值 | x=新值 y=新值 | x=$y |
x=${y?新值} | 新值输出到标准错误输出(屏幕) | x为空 | x=$y |
x=${y:?新值} | 新值输出到标准错误输出 | 新值输出到标准错误输出 | x=$y |
6、环境变量配置文件
6.1、环境变量配置文件
source命令
source 配置文件或 . 配置文件(点是source的缩写)
环境变量配置文件中主要是定义环境的操作环境生效的系统默认环境变量,比如:PATH、HISTSIZE、PSI、HOSTNAME等默认环境变量。
配置文件位置:
- /etc/profile
- /etc/profiled.d/*.sh
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
6.2环境变量配置文件作用
/etc/profile的作用:
- USER变量
- LOGNAME变量
- MAIL变量
- PATH变量
- HOSTNAME变量
- umask
- 调用/etc/profile.d/*.sh文件
/etc/bashrc的作用:
- PSI变量
- umask
- PATH变量
- 调用/etc/profile.d/*.sh文件
6.3、其它配置文件和登录信息
注销时生效的环境变量配置文件: ~/.bash_logout
其它配置文件: ~/bash_history
Shell登录信息
本地终端欢迎信息:/etc/issue
转义符 | 作用 |
---|---|
\d | 显示当前系统日期 |
\s | 显示操作系统名称 |
\l | 显示登录的终端号,比较常用 |
\m | 显示硬件体系结构,如:i386 |
\n | 显示主机名 |
\o | 显示域名 |
\r | 显示内核版本 |
\t | 显示当前系统时间 |
\u | 显示当前登录用户的系列号 |
远程终端欢迎信息: /etc/issue.net
- 转义符在/etc/issue.net文件中不能使用
- 是否显示此欢迎信息,由ssh的配置文件/etc/ssh/sshd_config决定,加入“Banner/etc/issue.net”行才能显示(重启SSH服务)
登录后欢迎信息:/etc/motd,不管是本地登录还是远程登录,都可以显示此欢迎信息。
Shell编程
1、基础正则表达式
- 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed命令可以用来支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
基础正则表达式:
元字符 | 作用 |
---|---|
* | 前一个字符匹配0次或任意多次 |
. | 匹配除了换行符外任意一个字符 |
^ | 匹配行首,如:^hello会匹配以hello开头的行 |
$ | 匹配行尾,如:hello&会匹配以hello结尾的行 |
[] | 匹配中括号中指定的任意一个字符,只匹配一个字符,如:[aoeiu]匹配任意一个元音字母,[0-9]匹配小写字母和一位数字构成的两位字符 |
[^] | 匹配除中括号的字符意外的任意一个字符,如:[^0-9]匹配一人一位非数字字符,[^a-z]表示任意一位非小写字母 |
\ | 转义符,用于将特色符合的含义取消 |
{n} | 表示其前面的字符恰好出现n次,如:[0-9]{4}匹配4位数字,[1][3-8][0-9]{9}匹配手机号码 |
{n,} | 表示其前面的字符出现不小于n次,如:[0-9]{2,}表示两位及以上数字 |
{n,m} | 表示其前面的字符至少出现n次,最多出现m次,如:[a-z]{6,8}匹配6到8位的小写字母 |
“*”前一个字符匹配0次,或任意多次
- grep “a*” test.txt #匹配所有内容,包括空白行
- grep “aa*” test.txt #匹配至少包含有一个a的行
- grep “aaa*” test.txt #匹配至少包含两个连续a的字符串
“.”匹配任意一个字符
- grep “s..d” test.txt # “s..d”会匹配在s和d这两个字母之间一定有两个字符的单词
- grep “s.*d” test.txt # 匹配在s和d字母之间有任意字符
- grep “.*” test.txt #匹配所有内容
“^”匹配行首,”$”匹配行尾
- grep “^M” test.txt #匹配以大写”M”开头的行
- grep “n$” test.txt #匹配以小写”n”结尾的行
- grep -n “^$” test.txt #会匹配空白行
“[]”匹配中括号中指定的任意一个字符,只匹配一个字符
- grep “s[ao]id” test.txt #匹配s和i字母中,是a或者o
- grep “[0-9]” test.txt #匹配任意一个数字
- grep “^[a-z] test.txt #匹配用小写字母开头的行
“[^]”匹配除中括号的字符以外的任意一个字符
- grep “^[^a-z]” test.txt #匹配不用小写字母开头的行
- grep “^[^a-zA-Z]” test.txt #匹配不用字母开头的行
“\”转义符
- grep “.$” test.txt #匹配使用”.”结尾的行
“{n}” 表示其前面的字符恰好出现n次
- grep “a{3}” test.txt #匹配a字母连续出现三次的字符串
- grep “[0-9]{3}” test.txt #匹配包含连续三个数字的字符串
“{n,m}” 匹配其前面的字符至少出现n次,最多出现m次
- grep “sa{1,3}i” test.txt #匹配在字母s和i之间有最少一个a,最多三个a
2、字符截取
2.1、cut字段提取命令
cut[选项]文件名
选项: -f列号: 提取第几列
-d分隔符: 按照之地给你分隔符分割列
示例:
cut -f 2 test.txt #获取第2列
cut -f 2,4 test.txt #获取第2和第4列
cut -d ":" -f 1,3 /etc/passwd #以“:”为分割符获取第1和第三行
cut命令的局限:空格符作为分割符无法识别
df -h | cut -d " " -f 1,3
2.2、printf命令
printf ‘输出类型输出格式’ 输出内容
输出类型:
%ns:输出字符串,n是数字指代输出几个字符
%ni:输出整数,n是数字指代输出几个数字
%m.nf: 输出浮点数,m和n是数字,指代输出的整数位数和小数位数,如%8.2f代表共输出8位数,其中2位是小数,6位是整数。
输出格式:
\a:输出警告声音
\b:输出退格键
\f:清除屏幕
\n:换行
\r:回车
\t:水平输出退格键,tab键
\v:垂直输出退格见,tab键
示例:
printf '%s %s %s\n' 1 2 3 4 5 6 #每3个为1组,换行输出
printf '%s' $(cat text.txt) #不调整输出格式
printf '%s\t %s\t %s\t %s\t \n' $(cat test.txt) #调整格式输出
在awk命令的输出中支持print和printf命令:
- print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令)
- printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
2.3、awk命令
awk ‘条件1{动作1} 条件2{动作2} …’ 文件名
条件(Pattern):
一般使用关系表达式作为条件
x>10 判断变量x是否大于10
x>=10 大于等于
x<=10 小于等于
动作(Action):
格式化输出
流程控制语句
BEGIN
awk 'BEGIN{printf "This is a transcript \n"} {printf $2 "\t" $6 "\n"}' test.txt
FS内置变量
cat /etc/passwd | grep "/bin/bash"|\ awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
END
awk 'END {printf "The End \n"} {printf $2 "\t" $6 "\n"} test.txt
2.4、sed命令
sed是一种几乎包括在所有UNIX平台的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
sed [选项]‘[动作]’ 文件名
选项:
-n:一般sed命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕。
-e:允许对输入数据应用多条sed命令编辑。
-i:用sed的修改结果直接修改读取数据的文件,而不是屏幕输出。
动作:
a: 追加,在当前行后添加一行或多行。添加多行时2,除最后一行外,每行末尾需要用“\”代表数据未完结。
c:行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需要用“\”代表数据未完结。
i:插入,在当前行前插入一行或多行,插入多行时,除最后贺一行外,每行末尾需要用“\”代表数据完结。
d:删除,删除指定的行。
p:打印,输出指定的行。
s:字符串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字符串/新字符串/g”
示例:
sed -n '2p' test.txt
sed '2a hello' test.txt #在第二行后追加hello
# 在第二行前插入两行数据
sed '2i hello \
> world' test.txt
sed '2c No such person' test.txt #数据替换
#sed ‘s/旧字符串/新字符串/g’文件名
sed '3s/98/66/g' test.txt #在第三行中,把98换成66
sed -i '3s/98/66/g' test.txt #直接在文件中把98替换为66
sed -e 's/Zs//g;s/Lisi//g' test.txt #同时把“Zs”和“Lisi”替换为空
3、字符处理
1、排序命令sort
sort [选项]文件名
选项:-f:忽略大小写
-n:以数值型进行排序,默认使用字符串型排序
-r:反向排序
-t:指定分隔符,默认时分隔符是制表符
-k n[,m]:按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)。
示例:
sort /etc/passwd #排序用户信息文件
sort -r /etc/passwd #反向排序
sort -t ":" -k 3,3 /etc/passwd #指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序
2、统计命令wc
wc [选项]文件名
选项:
-l:只统计行数
-w:只统计单词数
-m:只统计字符数
4、条件判断
1、按照文件爱你类型进行判断
测试选项 | 作用 |
---|---|
-b文件 | 判断该文件爱你是否存在,并且是否为块设备文件(是块设备文件为真) |
-c文件 | 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真) |
-d文件 | 判断该文件是否存在,并且是否为目录文件(是目录为真) |
-e文件 | 判断该文件是否存在(存在为真) |
-f文件 | 判断该文件是否存在,并且是否为普通文件(是普通文件为真) |
-L文件 | 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真) |
-p文件 | 判断该文件是否存在,并且是否为管道文件(是管道文件为真) |
-s文件 | 判断该文件是否存在,并且是否为非空(非空为真) |
-S文件 | 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真) |
两种判断格式:
test -e test.txt #第一种判断格式
[ -e test.txt ] #第二种判断格式
#第一个判断命令如果正确执行,则打印“yes”,否则打印“no”
[-d/root] && echo "yes" || echo "no"
2、按照文件权限进行判断
测试选项 | 作用 |
---|---|
-r文件 | 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真) |
-w文件 | 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真) |
-x文件 | 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真) |
-u文件 | 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真) |
-g文件 | 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真) |
-k文件 | 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真) |
示例:
# tmp下的test.txt是否有写权限,三组中只要有一组有写权限即为yes
[ -w /tmp/test.txt ] && echo "yes" || echo "no"
3、两个文件之间进行比较
测试选项 | 作用 |
---|---|
文件1 -nt 文件2 | 判断文件1的修改时间是否比文件2的新(如果新则为真) |
文件1 -ot 文件2 | 判断文件1的修改时间是否比文件2的旧(如果旧则为真) |
文件1 -ef 文件2 | 判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。这个方法可用于判断硬链接 |
示例:
#判断test.txt和test1.txt是否是硬链接
[ /tmp/test.txt -ef /tmp/test1.txt ] && echo yes ||echo no
4、两个整数之间比较
测试选项 | 作用 |
---|---|
整数1 -eq整数2 | 判断整数1是否和整数2相等 |
整数1 -ne整数2 | 判断整数1是否和整数2不相等(不相等位置) |
整数1 -gt整数2 | 判断整数1是否大于整数2(大于为真) |
整数1 -lt整数2 | 判断整数1是否小于整数2(小于位置) |
整数1 -ge整数2 | 判断整数1是否大于整数2(大于等于为真) |
整数1 -le整数2 | 判断整数1是否小于等于整数2(小于等于为真) |
5、字符串的判断
测试选项 | 作用 |
---|---|
-z 字符串 | 判断字符串是否为空(为空返回真) |
-n 字符串 | 判断字符串是否为非空(为非空返回真) |
字符串1 == 字符串2 | 判断字符串1是否和字符串2相等(相等返回真) |
字符串1 != 字符串2 | 判断字符串1是否和字符串2不相等(不相等返回真) |
示例:
[ -z "$name" ] && echo yes || echo no #判断name是否为空
[ "$aa" == "$bb" ] && echo yes || echo no #判断aa和bb是否相等
6、多重条件判断
测试选项 | 作用 |
---|---|
判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,最终结果才为真 |
判断1 -o 判断2 | 逻辑或,判断1和判断2有一个成立,最终的结果就为真 |
! 判断 | 逻辑非,使原始的判断式取反 |
5、流程控制
5.1、if语句
1、单分支if条件语句
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
fi
单分支条件语句注意点:
1. if语句使用fi结尾,和一般语句使用大括号结尾不同
2. [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
3. then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了
示例,判断分区使用率:
#!/bin/bash
#统计根分区使用率
#rate=$(df -h | grep /dev/sda1 | awk '{print $5}' | cut -d "%" -fl)
rate=$(df -h | grep /dev/sda1 | awk '{print $5}' | cut -d "%" -f1)
#把根分区使用率作为变量值赋予变量rate
if [ $rate -ge 5 ]
then
echo "Warning! /dev/sda3 is full !!"
fi
2、双分支if条件语句
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
示例:
#size=${du -sh /etc}
#!/bin/bash
#备份服务
#同步系统时间
date=$(date +%y%m%d)
size=$(du -sh /etc)
if [ -d /tmp/dbback ]
then
echo "Date is : $date" > /tmp/dbback/db.txt
echo "size is : $size" >> /tmp/dbback/db.txt
cd /tmp/dbback
tar -zcf etc_$date.tar.gz /etc db.txt &>/dev/null
rm -rf /tmp/dbback/db.txt
else
mkdir /tmp/dbback
echo "Date is : $date" > /tmp/dbback/db.txt
echo "size is : $size" >> /tmp/dbback/db.txt
cd /tmp/dbback
tar -zcf etc_$date.tar.gz /etc db.txt &>/dev/null
rm -rf /tmp/dbback/db.txt
fi
#!/bin/bash
#判断apache是否启动
port=$(nmap -sT 192.168.134.10 | grep tcp | grep http | grep 80 | awk '{print $2}')
if [ "$port" == "open" ]
then
echo "$(date) httpd is ok !! " >> /tmp/httpd_acc.log
else
/etc/re.d/init.d/httpd restart &>/dev/null
echo "$(date) httpd reboot ! " >> /tmp/httpd_err.log
fi
3、多分支if条件语句
if [条件判断式1]
then
当条件判断式1成立时,执行程序1
elif [条件判断式2]
then
当条件判断式2成立时,执行程序2
...更多的条件
else
当所有条件都不成立时,最后执行此程序
fi
示例:
#!/bin/bash
#判断用户输入内容
read -p "Please input a fileName: " file
#接收键盘输入并赋予变量
if [ -z "$file" ]
#判断file变量是否为空
then
echo "Error,please input a fileName"
exit
elif [ ! -e "$file" ]
#判断file是否存在
then
echo "Your input is not file"
exit 2
elif [ -f "$file" ]
#判断file是否为普通文件
then
echo "$file is a regulare file !"
elif [ -d "$file" ]
#判断file是否为目录文件
then
echo "$file is a directory !"
else
echo "$file is an other file !"
fi
5.2、case语句
case语句和if..elif..else语句一样都是多分支条件语句,和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
语法:
case $变量名 in
"值1")
如果变量的值等于值1),则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
...其他分支
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
示例:
#!/bin/bash
#判断用户输入
echo "you want to beijing,please input 1 !"
echo "you want to shanghai,please input 2 !"
echo "you want to shengzhen,please input 3 !"
read -t 30 -p "please input your choose : " cho
case "$cho" in
"1")
echo "your choose is beijing !"
;;
"2")
echo "your choose is shanghai !"
;;
"3")
echo "your choose is shengzhen !"
;;
*)
echo "your choose is no exist !"
;;
esac
5.3、for循环
语法一:
for 变量 in 值1 值2 值3...
do
程序
done
示例:
#!/bin/bash
#打印时间
for time in morning noon adternoon evening
do
echo "This time is $time !"
done
#!/bin/bash
#批量解压缩脚本
cd /usr/local/java
ls *.tar.gz >ls.log
for in in $(cat ls.log)
do
tar -zxf $i &>/dev/null
done
rm -rf /usr/local/java/ls.log
语法二:
for (( 初始值;循环控制条件;变量变化))
do
程序
done
示例:
#!/bin/bash
#从1加到100的和
s=0
for(( i=1;i<=100;i=i+1))
do
s=$(( $s+$i ))
done
echo "The sum of from 1 to 100 is : $s"
#!/bin/bash
#批量添加用户
read -t 30 -p "input name: " name
read -t 30 -p "input num: " num
read -t 30 -p "input password: " password
if [ ! -z "$name" -a ! -z "$num" -a ! -z "$password" ]
then
y=$(echo $num | sed 's/^[0-9]*$'//g)
if [ -z "$y" ]
then
for(( i=1;i<=$num;i=i+1))
do
useradd $name$i &>/dev/nu
ll
echo $password | passwd --stdin "$name$i" &>/dev/null
done
if
if
5.4、while循环
1、while循环是不定循环,也称作条件循环,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。
语法:
while [条件判断式]
do
程序
done
示例:
#!/bin/bash
#从1加到100
i=1
s=0
while [ $i -le 100 ]
do
s=$(( $s+$i ))
i=$(( $i+1 ))
done
echo "The sum is: $s"
2、until循环和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序,循环条件成立则终止循环。
语法:
until [条件判断式]
do
程序
done
示例:
#!/bin/bash
#从1加到100
i=1
s=0
until [ $i -gt 100 ]
#循环直到变量i的值大于100,就停止循环
do
s=$(( $s+$i))
i=$(( $i+1 ))
done
echo "The sum is: $s"
6、自定义函数
[ function ] funname [()]
{
action;
[return int;]
}
function start() / function start/ start() 定义函数的三种写法
注意:
1. 必须在调用函数的地方之前,先声明函数。shell脚本是逐行运行的。不会像其他语言一样先预编译。
2. 函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加将以最后一条命令运行结果,做为返回值。return后跟数值n(0~255)。