shell(一)
什么是shell?
- Shell(外壳) 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
-
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
-
Shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)
常见的shell种类?
在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux中默认的shell是/bin/bash(重点),流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特点以及用途。
shell入门
bash常见操作:
- 常见快捷键:
-
ctrl+c 终止前台运行的程序 ctrl+d 退出 等价exit ctrl+l 清屏 ctrl+a 光标移到命令行的最前端 //编辑命令 ctrl+e 光标移到命令行的后端 //编辑命令 ctrl+u 删除光标前所有字符 //编辑命令 ctrl+k 删除光标后所有字符 //编辑命令 ctrl+r 搜索历史命令 //命令需连续
-
- 常见通配符:
-
*: 匹配0或多个任意字符 ?: 匹配任意单个字符 [list]: 匹配[list]中的任意单个字符 //[abc]、[1-4] [!list]: 匹配除list中的任意单个字符 {string1,string2,...}:匹配string1,string2或更多字符串
#创建多个文件:touch {1..13}.jpg
-
- $()和${}
- $( )中放的是命令,相当于` `,例如todaydate=$(date +%Y%m%d)意思是执行date命令,返回执行结果给变量todaydate,也可以写为todaydate=`date +%Y%m%d`;
- ${ }中放的是变量,例如echo ${PATH}取PATH变量的值并打印,也可以不加括号比如$PATH
- bash中的引号:
- 单引号'' :会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
使用流程:
- 创建.sh文件
- 编写shell代码
#!/bin/bash
#脚本第一行 , #!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用哪一种Shell#以下内容是对脚本的基本信息的描述
# Name: 名字
# Desc:描述describe
# Path:存放路径
# Usage:用法
# Update:更新时间#下面就是脚本的具体内容
commands
... - 执行shell脚本 (chmod +x):脚本路径;/bin/bash 脚本路径,如果脚本没有权限,可以使用第二种方式执行
shell进阶
变量
- 变量分为本地变量,环境变量,全局变量
- 环境变量:当前进程有效,并且能够被子进程调用。
- 查询当前用户的所有变量(临时变量与环境变量) //set
- export //将当前变量变成环境变量,比如export a=1
- 全局变量
-
$HOME/.bashrc 当前用户的bash信息(aliase、umask等) $HOME/.bash_profile 当前用户的环境变量 $HOME/.bash_logout 每个用户退出当前shell时最后读取的文件 /etc/bashrc 使用bash shell用户全局变量 /etc/profile 系统和每个用户的环境变量信息 /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout
-
-
$#:脚本后面接的参数的个数 $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 $@: 脚本后面所有参数,参数是独立的,也是全部输出 $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错 若退出状态值为0,表示命令运行成功 若退出状态值为127,表示command not found 若退出状态值为126,表示找到了该命令但无法执行(权限不够) 若退出状态值为1&2,表示没有那个文件或目录 $$:当前所在进程的进程号 echo $$ eg:kill -9 `echo $$` = exit 退出当前会话 $!:后台运行的最后一个进程号 (当前终端) # gedit & !$ 调用最后一条命令历史中的参数 !! 调用最后一条命令历史 $0:当前执行的进程/程序名 echo $0 $1~$9 位置参数变量 ${10}~${n} 扩展位置参数变量(多位数要括起来,比如111,21,32) 第10个位置变量必须用{}大括号括起来 了解$*和$@的区别: #!/bin/bash for i in "$@";do echo $i done echo "======我是分割线=======" for i in "$*";do echo $i done
-
变量相关操作
1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来 变量名=变量值 2. 变量的获取方式: $变量名 ${变量名} [root@server ~]# A=123456789 [root@server ~]# echo $A 123456789 [root@server ~]# echo ${A:0:3} //0代表从第1个字符开始截取,3代表截取3个字符 123 3. 取消变量: unset 变量名(只读变量不可取消) 4. 区分大小写,同名称但大小写不同的变量名是不同的变量 5. 变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符 6. 命令的执行结果可以保存到变量 [root@server ~]# uname -r 2.6.32-431.el6.x86_64 [root@server ~]# kernel=`uname -r` [root@server ~]# echo $kernel 2.6.32-431.el6.x86_64 7. 数组 数组定义:用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为: array=(var1 var2 var3 var4) 或者 array[0]=v1 array[1]=v2 array[3]=v3 读取数组: ${array [i]} i表示元素 使用@ 或 * 可以获取数组中的所有元素: 获取第一个元素 echo ${user[0]} echo ${user[*]} 获取数组里的所有元素 echo ${!array[@]} 获取数组元素的索引下标 echo ${array[@]:1:2} 访问指定的元素 [root@server ~]# echo ${user[@]} u1 u2 u3 [root@server ~]# A=123456789 [root@server ~]# echo ${A:3:4} 4567 [root@server ~]# echo ${user[@]:1:2} u2 u3 举例: # for i in `echo ${user[*]}`;do echo "hello,$i";done 8. 有类型变量 declare -i 将变量看成整数 -r 使变量只读 readonly -x 标记变量通过环境导出 export [root@server shell01]# a=10 [root@server shell01]# b=20 [root@server shell01]# c=$a+$b [root@server shell01]# echo $c 10+20 [root@server shell01]# [root@server shell01]# declare -i a=10 [root@server shell01]# declare -i b=20 [root@server shell01]# declare -i c=$a+$b [root@server shell01]# echo $c 30 9. 交互式定义变量的值 read 主要用于让用户去定义变量值 -p 提示信息 -n 限制字符数 -s 不显示 -t 超时(默认单位秒) 10. 其他变量(扩展) 1)取出一个目录下的目录和文件:dirname和 basename 2)变量"内容"的删除和替换 一个“%”代表从右往左去掉一个/key/ 两个“%%”代表从右往左最大去掉/key/ 一个“#”代表从左往右去掉一个/key/ 两个“##”代表从左往右最大去掉/key/ # A=/root/Desktop/shell/mem.txt # echo $A /root/Desktop/shell/mem.txt # dirname $A 取出目录 /root/Desktop/shell # basename $A 取出文件 mem.txt # echo ${A%/*} 从右往左去掉“/*”内容 /root/Desktop/shell # echo ${A%%.*} 从右往左最大长度去掉.后的内容 /root/Desktop/shell/mem # echo ${A%%.txt} 从右往左最大长度去掉.txt内容 /root/Desktop/shell/mem # echo ${A##/*/} 从左往右最大去掉所有"/*/" mem.txt # echo ${A#/*/} Desktop/shell/mem.txt //以下扩展内容自己练习完成 1000 url=www.taobao.com 1001 echo ${#url} 获取变量的长度 1008 echo ${url#*.} 1009 echo ${url##*.} 1011 echo ${url%.*} 1012 echo ${url%%.*} 替换:/ 和 // 1015 echo ${url/ao/AO} 1017 echo ${url//ao/AO} 贪婪替换 替代: - 和 :- +和:+ 1019 echo ${abc-123} 1020 abc=hello 1021 echo ${abc-444} 1022 echo $abc 1024 abc= 1025 echo ${abc-222} ${变量名-新的变量值} 或者 ${变量名=新的变量值} 变量没有被赋值:会使用“新的变量值“ 替代 变量有被赋值(包括空值): 不会被替代 1062 echo ${ABC:-123} 1063 ABC=HELLO 1064 echo ${ABC:-123} 1065 ABC= 1066 echo ${ABC:-123} ${变量名:-新的变量值} 或者 ${变量名:=新的变量值} 变量没有被赋值或者赋空值:会使用“新的变量值“ 替代 变量有被赋值: 不会被替代 1116 echo ${abc=123} 1118 echo ${abc:=123} [root@server ~]# unset abc [root@server ~]# echo ${abc:+123} [root@server ~]# abc=hello [root@server ~]# echo ${abc:+123} 123 [root@server ~]# abc= [root@server ~]# echo ${abc:+123} ${变量名+新的变量值} 变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代 变量有被赋值: 会被替代 [root@server ~]# unset abc [root@server ~]# echo ${abc+123} [root@server ~]# abc=hello [root@server ~]# echo ${abc+123} 123 [root@server ~]# abc= [root@server ~]# echo ${abc+123} 123 ${变量名:+新的变量值} 变量没有被赋值:不会使用“新的变量值“ 替代 变量有被赋值(包括空值): 会被替代 [root@server ~]# unset abc [root@server ~]# echo ${abc?123} -bash: abc: 123 [root@server ~]# abc=hello [root@server ~]# echo ${abc?123} hello [root@server ~]# abc= [root@server ~]# echo ${abc?123} ${变量名?新的变量值} 变量没有被赋值:提示错误信息 变量被赋值(包括空值):不会使用“新的变量值“ 替代 [root@server ~]# unset abc [root@server ~]# echo ${abc:?123} -bash: abc: 123 [root@server ~]# abc=hello [root@server ~]# echo ${abc:?123} hello [root@server ~]# abc= [root@server ~]# echo ${abc:?123} -bash: abc: 123 ${变量名:?新的变量值} 变量没有被赋值或者赋空值时:提示错误信息 变量被赋值:不会使用“新的变量值“ 替代 说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能
只读变量(了解)
#!/bin/bash
a=1 readonly a a=2 #会报错
只读变量不可删除,declare也可以
流程控制语句
#!/bin/bash #一个条件 if condition then command ... fi #两个条件 if condition then command ... else condition command ... fi #n个条件 if condition1 then command ... elif condition2 then command ... else command ... fi
条件判断
格式1: test 条件表达式
格式2: [ 条件表达式 ]
格式3: [[ 条件表达式 ]] 支持正则 =~
运算符
在shell中,运算符和其他编程脚本语言一样,常见的有算数运算符、关系运算符、
逻辑运算符、字符串运算符、文件测试运算符等
算数运算符
运算符 说明 举例 + 加法 `expr $a + $b`
- 减法 `expr $a - $b`
* 乘法 `expr $a \* $b`
/ 除法 `expr $b / $a`
% 取余 `expr $b % $a`
= 赋值 a=$b == 相等。 [ $a == $b ]
!= 不相等。 [ $a != $b ]
注意:
- 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
- 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
- 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
- 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 说明 举例 -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] -ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] -ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ]
逻辑运算符
运算符 说明 举例 ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。 -o/|| 或(或者)运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。 -a/&& 与(并且)运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
逻辑判断符号:
-a 和 && (and 逻辑与)
-o 和 ||(or 逻辑或)
! 逻辑非
[ 1 -eq 1 -a 1 -ne 0 ]
[ 1 -eq 1 -o 1 -ne 1 ]
[root@server shell01]# [ 1 -eq 0 ] && echo true || echo false
false
[root@server shell01]# [ 1 -eq 1 ] && echo true || echo false
true
优先级:
-a(&&) > -o(||)> !
字符串运算符
运算符 说明 举例 = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] -n 检测字符串长度是否为0,不为0返回 true。 [ -n $a ] str 检测字符串是否为空,不为空返回 true。 [ $a ]
文件测试运算符
文件测试运算符用于检测 Unix/Linux 文件的各种属性。
操作符 说明 举例 -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] -p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ]
示例
示例: 数值比较: [root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin" [root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin" [root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin" 类C风格的数值比较: 1159 ((1==2));echo $? 1160 ((1<2));echo $? 1161 ((2>=1));echo $? 1162 ((2!=1));echo $? 1163 ((`id -u`==0));echo $? 1209 ((a=123));echo $a 1210 unset a 1211 ((a==123));echo $? 注意:在(( ))中,=表示赋值;==表示判断 字符串比较: 注意:双引号引起来,看作一个整体 1196 a='hello world';b=world 1197 [ $a = $b ];echo $? 1198 [ "$a" = "$b" ];echo $? 1199 [ "$a" != "$b" ];echo $? 1200 [ "$a" !== "$b" ];echo $? 错误 1201 [ "$a" == "$b" ];echo $? 1202 test "$a" != "$b";echo $? 注意:= 和 == 在 [ 字符串 ] 比较中都表示判断 字符串一定要用“” 思考:[ ] 和 [[ ]] 有什么区别? 1213 a= 1214 test -z $a;echo $? 1215 a=hello 1216 test -z $a;echo $? 1217 test -n $a;echo $? 1217 test -n "$a";echo $? # [ '' = $a ];echo $? -bash: [: : unary operator expected 2 # [[ '' = $a ]];echo $? 0
[[]]:可以比较为空
1278 [ 1 -eq 0 -a 1 -ne 0 ];echo $? 1279 [ 1 -eq 0 && 1 -ne 0 ];echo $? 1280 [[ 1 -eq 0 && 1 -ne 0 ]];echo $?
shell中sh, exec, source, fork, ./的区别