一.Shell基本概念
(一)Shell是什么?
在我们学习Linux时,通过不同的终端连接自己的Linux系统,此时连接用户和内核的桥梁就是Shell,可以说它是一个帮助我们安全、高效地使用内核。专业点说,Shell是一个命令解释器,它可以通过接受用户输入的Shell命令才控制程序或控制OS。
通俗的说,Shell就是一个外壳,它包裹着Linux内核,通过Shell,我们就可以访问OS。
(二)什么是脚本语言(Scripts)
计算机的编程语言主要分为三类:
- 1.机器语言:二进制代码
- 2.汇编语言:面向机器的程序设计语言
- 3.高级语言:一般面向用户,易学,易维护,可移植性高。
在此着重解释高级语言,按照转换方式可以分为以下两类:
- 1.编译型语言:如C、C++,想要运行需要经过预处理-编译-链接的过程。
- 2.解释型语言:不需要编译,每个语句都是在执行的时候才翻译。
而脚本语言也属于解释型语言,再次基础上,它们一般需要对应的脚本引擎或者解释器才能运行,这也是为什么Shell被叫做命令解释器的原因。
同时它们简单、易学、易用,在日常工作时,能够带来很大的便利,但相对于编译型语言,它们执行的速度还是很慢,毕竟每执行一句都要翻译一次(日常使用中脚本语言已经够快了)。
常见的脚本语言有:Lua、Shell、Sql、PHP、Python等等
(三)Shell脚本语言和Linux命令行的异同
我们平时用的大部分指令其实都是Shell提供的,如ls,cd等等,当然也有很多是Linux内核提供的,想要查看自己Shell下的内置指令有哪些,可以使用help指令。下图就是笔者云服务器上Linux内置的Shell指令。
(四)Shell和Shell脚本语言
Shell是解释器,解释的Shell脚本语言,Shell脚本语言不是Shell本身。
常见的Shell解释器有bash、sh、ash、csh等等,习惯上我们都把它们称作Shell。
- bash:Linux系统默认使用的Shell,可以使用help指令查找内置的指令集,可以快速查找和修改指令,同时支持快速查命令或者文件等等。
- sh:一般见于各种UNIX系统。
(五)什么场景下使用Shell
Shell现在基本上是各UNIX、Linux系统之间通用的功能,而今经过POSIX的标准化,因此Shell脚本基本只需要写一次,就能应用到很多地方,这也是它的特点:可以表达复杂操作、移植性不错、开发方便。
当然,脚本语言和编译语言的效率差距还是非常大的,以下场景一般不适用Shell:
- 1.资源密集型任务,如排序。
- 2.大量的高精度计算
- 3.跨平台,需要移植
- 4.复杂的应用,需要使用结构化编程
- 5.对于影响全局性的关键任务
- 6.闭源或者安全性要求高
- 7.需要硬件、GUI、数据结构、I/O接口、socket接口中的一个
- 8.项目依赖性较强
二.Shell脚本初认识
(一 )建立和运行Shell脚本
首先让我们先创建一个脚本文件,运行起来。
#! /bin/bash
#hello world example
echo hello
# Linux中用#!及该字符串后面的信息来确定文件类型,后面的路径让它确定这个一个解释脚本
# 第三行打印一个字符
chomd a+x hello.sh
#为了确定脚本能正确运行,请设置权限,另外,为了安全,在学习脚本时建议不要使用root账户,因为脚本语言不编译
打印一个字符串怎么打印呢?在Shell中,空格作为分隔参数的指标,所以当我们想要打印字符串的时候可以用双引号或者单引号标注。
#! /bin/bash
#hello world example
#echo hello
echo "hello Shell"
echo 'hello Shell!'
那单引号和双引号有区别吗?有的,先按下不表
(二)定义Shell变量
1.基本规则
接下来我们学习下Shell中定义变量的规则:
- 只能包含字母、数字和下划线
- 不能以数字开头,但是可以包含
- 避免使用Shell关键字,如if、if、then、else、esle等等
- 习惯上用大写字母表示常量
- 避免使用空格,空格一般用作参数分割
- 使用"$"符号引用变量
#! /bin/bash
#hello world example
#echo hello
# echo "hello Shell"
# echo 'hello Shell!'
#echo "hello shell"
a="hello shell"
b = hello
echo $a $b
# 使用$引用变量
第8行由于使用空格,导致Shell无法正确识别,同时因为无需编译,下一行依旧执行。
2.只读变量
可以使用readonly指令把变量定义成只读。
name="Shell"
readonly name
name="hello"
echo $name
将变量变成只读,再修改,结果报错,修改失败。
3.删除变量
a=1
unset a
echo $a
#删除变量a,结果不打印
4.定义字符串、单双引号的异同
之前说过,可以用单引号或双引号定义字符串,二者区别在于前者定义的字符串里的变量是无效的,只会原样输出,但是双引号会替换指定内容。
a=1
str1="hello $a"
str2='hello $a'
echo $str1 $str2
对应的,双引号中可以有变量,会指定替换,同时可以出现转义字符。
5.拼接字符串
# 单双字符串都可以拼接字符串
#拼接字符串
#双引号拼接
name="str one"
foo1="hello, "$name" ! "
foo2="hello, ${name} ! "
echo $foo1 $foo2
#单引号拼接
foo3='hello, '$name' !'
foo4='hello, ${$name} !'
echo $foo3 $foo4
如上,说明一下,花括号一般用来分割变量的范围。
6.定义数组
bash支持一维数组,不支持多维,但是没有限定数组大小。
# 定义数组
array=(1 2 3 4 5)
echo ${array[@]} ${array[0]}
#支持单独定义某个元素,用@可以获取所有元素,可以不使用连续的下标
7.默认变量
在Shell中,一般都配置了默认的变量,接下来我们认识一下。
- $0:执行的文件名
- $1:脚本文件的第一个参数
- $#:传递到脚本的参数个数
- $*:以一个单字符串显示所有向脚本传递的参数
-
- $?:显示最后命令的退出状态,0表示没有错误,其它值表示有错误例子a.sh
三.Shell的常见内置指令
想要完全了解当前主机下Shell内置指令有哪些,可以使用help指令,这里就只介绍几个常用的内嵌指令。
(一)echo
-
echo指令可以向终端打印文本信息
-
-e 允许我们解释反斜杠、换行符、制表符等等
-
-n 输出时不在末尾添加新行
-
支持输入输出重定向
其他参数就不介绍了,有需要的可以help指令查询一下
echo "----------打印文本--------------------"
echo "----------解释特殊字符----------------"
echo -e "hello,
Linux, "
echo "----------------换行-----------------"
echo -n "hello Linux!"
演示下重定向
(二)read
read指令可以从键盘中读取变量内容
- -a:把读取的数据赋值给数组array,从下标0开始
- -p:显示提示信息,提示内容为prompt
- -r: 原样读取(Raw mode),不把反斜杠字符解释为转义字符
- -n:读取num个字符,而不是整行字符
- -s:静默模式(Slient mode),不会在屏幕上显示输入的字符,输入密码或其它确认信息时常用
- -t:设置超时时间
read
echo $REPLY
#$REPLY:read指令的默认变量名,没有提供变量名,那么读取的数据就会被放在REPLY中
read -p "请输入姓名:" name
read -p "请输入性别:" sex
echo "姓名:${name}"
echo "性别: ${sex}"
read -t 10 -sp "请输入密码(10s):" pwd1
echo
read -t 10 -sp "请再次输入密码(10s):" pwd2
printf "\n"
if [ $pwd1 == $pwd2 ]
then
echo "密码一致,验证通过~"
else
echo "密码错误,验证失败!"
fi
(三)declare
众所周知,shell变量是弱类型变量,默认情况下都是字符串型。字符串不能直接进行数学运算,如果想要进行数学运算,便可使用declare声明变量类型。
#declare [+/-] [选项] 变量名
#+/- : 取消/设定变量类型的属性
- -a:设定为数组array
- -A:设置为key-value(键对值)关联数组
- -f:定义为函数
- -i:定义为整数
- -r:定义为只读
#一般格式
a=1+1
declare -i b=1+1
echo $a
echo $b
#普通数组
declare -a arr1=("李明" 33 "hobbit1")
echo ${arr1[*]}
echo ${arr1[1]}
declare -a arr2=([0]="王强" 55 "hobbit2")
echo ${arr2[@]}
#关联数组
declare -A arr3=(["name"]="王武" [age]=34 [hobbit]="hobbit3")
echo ${arr3[@]}
echo ${arr3["age"]}
(四)test
1.数值测试
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。以下几个符号也是Shell中支持的关系运算符。
- -eq:等于则为真
- -ne:不等于则为真
- -gt:大于则为真
- -ge: 大于等于则为真
- -lt:小于则为真
- -le:小于等于则为真
- eq表示等于--equal ,ne表示不等于--no equal,gt表示大于--greater than,lt表示小于--less than
num1=100
num2=200
if test $num1 -eq $num2
then
echo "两个数相等!"
else
echo "两个数不相等!"
fi
2.字符串测试
- =:等于则为真
- !=:不相等则为真
- -z:字符串的长度为零则为真
- -n:字符串的长度不为零则为真
num1="helloaa"
num2="hello"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
3.文件测试
- -e [文件名]:如果文件存在则为真
- -r [文件名]:如果文件存在且可读则为真
- -w [文件名]:如果文件存在且可写则为真
- -x [文件名]:如果文件存在且可执行则为真
- -s [文件名]:如果文件存在且至少有一个字符则为真
- -d [文件名]:如果文件存在且为目录则为真
- -f [文件名]: 如果文件存在且为普通文件则为真
- -c [文件名]: 如果文件存在且为字符型特殊文件则为真
- -b [文件名]:如果文件存在且为块特殊文件则为真
cd /home/study
if [ -e log.txt ]
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
同时,Shell还支持将与(-a)、或(-o)、非(!)连接起来,这里就不再详细介绍了。
四.Shell基本运算符
(一)expr
Shell和其他语言一样,支持多种运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试语言符。
但是原生bash并不支持简单的数学计算,可以通过其他命令来实现,比如expr。
#expr
val=`expr 2 + 2`
echo "和为:$val"
#1.注意格式,使用的是反引号,不是单引号
#2.表达式和运算符之间要有空格,不能写成“2+2”
(二)算术运算符
- [+]:加法
- [-]:减法
- [\*]:乘法
- [/]:除法
- [%]:取余
- [=]:赋值
- [==]:相等,用来比较字符串,相同返回true
- [!=]:不相等,用来比较字符串,不相同返回true
a=20
b=10
echo `expr $a + $b`
echo `expr $a - $b`
echo `expr $a \* $b`
echo `expr $a / $b`
echo `expr $a % $b`
echo `expr $a == $b`
echo `expr $a != $b`
x="xx"
y="xy"
echo `expr $x == $y`
echo `expr $x != $y`
#尽管如此,“==”和“!=”也能比较数字
(三)关系运算符
Shell中的关系运算符只支持数字,不支持字符串,除非字符串的值为数字。
- -eq:等于则为真
- -ne:不等于则为真
- -gt:大于则为真
- -ge: 大于等于则为真
- -lt:小于则为真
- -le:小于等于则为真
- eq表示等于--equal ,ne表示不等于--no equal,gt表示大于--greater than,lt表示小于--less than。
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : 为真,a 等于 b"
else
echo "$a -eq $b: 为假,a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: 为真,a 不等于 b"
else
echo "$a -ne $b : 为假,a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: 为真,a 大于 b"
else
echo "$a -gt $b: 为假,a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: 为真,a 小于 b"
else
echo "$a -lt $b: 为假,a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: 为真,a 大于或等于 b"
else
echo "$a -ge $b: 为假,a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: 为真,a 小于或等于 b"
else
echo "$a -le $b: 为假,a 大于 b"
fi
(四)布尔运算符
- !:非运算或运算,有一个表达式为 true 则返回 true。,表达式为 true 则返回 false,否则返回 true。
- -o:非运算,表达式为 true 则返回 false,否则返回 true。
- -a:与运算,两个表达式都为 true 才返回 true。
x=10
y=20
if [ $x != $y ]
then
echo "$x != $y : 为真,x不等于y"
else
echo "$x != $y : 为假,x等于y"
fi
if [ $x -gt 10 -o $y -gt 10 ]
then
echo "为真, $x 大于 10 或 $y 大于 10"
else
echo "为假, $x 和 $y 都不大于10"
fi
if [ $x -gt 5 -a $y -gt 5 ]
then
echo "为真, $x 和 $y 都大于5"
else
echo "为假, $x 和 $y 都不大于5"
fi
(五)逻辑运算符
- &&:逻辑的and
- ||:逻辑上的or
x=10
y=20
if [[ $a -gt 100 && $b -gt 100 ]]
then
echo "true"
else
echo "false"
fi
if [[ $a -lt 10 || $b -lt 10 ]]
then
echo "true"
else
echo "false"
fi
#"[]"用于条件测试
(六)字符串运算符
- =:检测两个字符串是否相等,相等返回true
- !=:检测两个字符串是否不相等,不相等返回 true。
- -z: 检测字符串长度是否为0,为0返回 true。
- -n:检测字符串长度是否不为 0,不为 0 返回 true。
- $:检测字符串是否不为空,不为空返回 true。
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b, 为真, a 等于 b"
else
echo "$a != $b, 为假, a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b, 为真, a 不等于 b"
else
echo "$a != $b, 为假, a 不等于 b"
fi
if [ -z $a ]
then
echo "为真,长度为0"
fi
if [ -n $a ]
then
echo "为真,长度为 ${#a}"
fi
if [ $a ]
then
echo "为真,字符串不为空"
fi
(七)文件测试运算符
以下是文件测试运算符的参数,和其他运算符使用方法一致,文件测试多种多样,这里就不再示例了。
- -b :检测文件是否是块设备文件,如果是,则返回 true。
- -c :检测文件是否是字符设备文件,如果是,则返回 true。
- -d:检测文件是否是目录,如果是,则返回 true。
- -f :检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
- -g :检测文件是否设置了 SGID 位,如果是,则返回 true。
- -k :检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。
- -p: 检测文件是否是有名管道,如果是,则返回 true
- -u:检测文件是否设置了 SUID 位,如果是,则返回 true。
- -r:检测文件是否可读,如果是,则返回 true。
- -w: 检测文件是否可写,如果是,则返回 true。
- -x:检测文件是否可执行,如果是,则返回 true。
- -s: 检测文件是否为空(文件大小是否大于0),不为空返回 true。
- -e:检测文件(包括目录)是否存在,如果是,则返回 true。
五.Shell流程控制
(一)if语句
1.单if
if [ condition ]
then
command1
command2
command3
......
commandn
fi
#末尾的fi就是if的倒写,表示语句块的结束
#注意:Shell中的if语句需要使用方括号,而且两边一定要有空格分割
2.单if esle
if [ condition ]
then
command1
command2
command3
......
commandn
else
command
fi
#注意:shell中else部分不能为空,没有就不要写
3.多if else
if [ condition1 ]
then
command1
elif [ condition2 ]
then
command2
else
commandN
fi
#示例
a=10
b=20
if [ $a -eq $b ]
then
echo "$a 等于 $b"
elif [ $a -gt $b ]
then
echo "$a 大于 $b "
elif [ $a -lt $b ]
then
echo "$a 小于 $b "
fi
4.if与test指令结合
if test condition
then
command
fi
#if和test结合的时候就不用方括号了
a=10
b=20
if test $[a] -lt $[b]
then
echo "$a 小于 $b"
fi
(二)for循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
#in列表里存储了for循环的变量值,可以包含替换、字符串和文件名
#同样,done表示循环结束
for val in 1 2 3 4 5
do
echo "The val is : $val"
done
#顺序输出字符
for str in This is a string
do
echo $str
done
(三)while循环
while condition
do
command
done
#示例, 循环输出1到5
val=1
while(( $val<=5 ))
do
echo $val
let "val++"
done
#以上是哦那个了Bash let指令,用于执行多个表达式,不需要加上$表示变量
(四)until循环
#until循环会一直执行命令直到条件为true,和while相反
until condition
do
command
done
val=0
until [ $val -gt 10 ]
do
echo $val
val=`expr $val + 1`
done
(五)case...esac
这个其实就对应其他语言的switch语句,是多分支的选择结构。
case 值 in
1)
command1
......
;;
2)
command1
......
;;
*)
command1
......
;;
esac
#最后如果没有匹配的,可以用*捕获该值
echo "请输入1到3的数字"
echo '你输入的数字为:'
read num
case $num in
1) echo "你选择了1" ;;
2) echo "你选择了2" ;;
3) echo "你选择了3" ;;
*) echo "你没有选择范围内的数字" ;;
esac
最后,对于循环语句,Shell同样支持使用“break”跳出所有循环,“continue”跳出所有循环,和其他语言稍微不同,但用法类似,不再过多介绍。
六.Shell函数
(一)基本格式
同样的,Shell也支持我们定义函数供我们调用,格式如下:
[ function ] 函数名 [()]
{
command;
返回值
}
#可以带function fun()定义,也可以直接定义,不带参数
demoFun()
{
echo "hello Shell, this is the first function"
return 0
}
echo "------开始执行------"
demoFun
echo "------执行结束------"
AddFun()
{
echo "计算两数之和"
echo "输入第一个数字-> "
read num1
echo "输入第二个数字->"
read num2
return $(($num1+$num2))
}
AddFun
echo "两数之和为-> $?"
(二)返回值
Shell每个命令都有退出码,退出码从0-255,0为正确退出,1-255为错误退出码。在定义的函数中,一般返回最后一个命令的退出码,如果超出255,则会取模。
一般最后可以使用return返回返回值,但这样就很不灵活,因为我们只能返回整数。但是我们可以使用echo,echo可以把输出到标准输出返回,这样就可以返回任何类型的数据了。
(三)函数传参
Shell的参数不能够直接设置,但是在调用时可以传递参数,你传入什么参数他就接受什么参数。
fun()
{
echo "参数1-> $1"
echo "参数9-> $9"
echo "参数10-> $10"
echo "参数10-> ${10}"
echo "参数11-> ${11}"
echo "输出所有参数 $*"
}
fun 0 1 2 3 4 5 6 7 8 9 10
#从第10个参数开始,要用${n}
七.Shell特殊符号讲解
细心的朋友可能会发生,我们在讲解上述语法的时候,有的时候用方括号,有的时候用大括号,有的时候用两个小括号,其中有什么区别?接下来讲解下Shell中国特殊符号的用法
(一)单引号、双引号、反引号
在第二章节里我们简单讲解了单引号、双引号的区别,其实很简单,单引号所见即所得,原样输出,双引号会解析特殊变量,如“$”, 反斜杠等。
在讲解expr指令时,介绍了反引号,他在esc键的下方,用于命令替换,即先执行反引号里的命令,再将结果加入原命令。
(二)小括号
1.单小括号--()
- 相当于一个命令组,单小括号的内容会先用一个子Shell顺序执行,括号中多个命令用分号隔开,最后一个不需要分号,不必有空格
- 相当于命令替换,例如$(cmd),会将括号内的内容先执行一遍,再加入原命令中重新执行
- 定义数组
2.双小括号--(())
- 用于整数计算:不支持浮点数,((exp))可以拓展计算一个表达式的值,同时也有自己的返回值。
- 运行C语言代码:双小括号的运算符只要满足C语言运算规则,都可以用运算,结果转化为10进制
- 重新定义变量值
- 算术运算符比较,常见于语句判断中
(三)中括号
1.单中括号--[]
- 条件判断的表示:在Bash的内部指令中,[]和test指令作用等同,不用绝对路径指明时,一般都是使用bash自带的命令。在常用的if/else语句中,左中括号用来调用test命令标识,右中括号用来结束条件判断,这也是为什么if和test混用的时候不再需要中括号的原因。
- 比较运算符:在讲解运算符时已经说过,单中括号可以用与运算符比较
- 字符范围:用来作为正则表达式的一部分,描述一个匹配的字符范围(后续讲解)
- 索引编号:单中括号可以用来引用数组中的元素。
#test和if混用,不用单中括号
a=10
b=20
if test $[a] -lt $[b]
then
echo "$a 小于 $b"
fi
# 判断字符串 str 是否为空
str=""
if [ -z $str ]; then
echo "str is empty"
fi
#引用数组元素
arr=(10 20 30 40)
echo $[arr[0]]
2.双中括号--[[]]
-
保护字符:在双中括号的内容,不会发生文件名的拓展或者单词分割。因此使用双中括号进行判断时,不需要再用引号。
-
支持字符串的模式匹配。
-
支持更复杂的逻辑判断:在if语句中,单中括号有的时候很容易出现逻辑错误,双中括号能尽量避免。
-
支持正则表达式的匹配。
# 判断变量 a 是否为空
a=""
if [[ -z $a ]]; then
echo "a is empty"
fi
# 判断变量 b 是否为非空
b="hello"
if [[ -n $b ]]; then
echo "b is not empty"
fi
# 判断变量 c 是否以 h 开头,以 o 结尾
c="hello"
if [[ $c == h*o ]]; then
echo "c matches the pattern h*o"
fi
# 判断变量 d 是否是一个 IP 地址
d="192.168.1.1"
if [[ $d =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "d is a valid IP address"
fi
其实单中括号和双中括号的差别就在于前者容易出现逻辑错误,且不支持通配符和正则表达式的匹配,也不支持&&、||,只能使用-a和-o来表示。
(四)大括号(花括号)
- 对大括号内的内容进行拓展,可以用点号分割,也可以用逗号分割。
- 创建代码块:与单中括号不同,大括号不会新建子Bash运行,而是在当前Bash下运行,使用注意第一个命令和左括号一定要有一个空格,最后用分号结尾。
- 划分变量:有的时候我们想要连续输出多个变量,且无法使用空格分割,就可以用大括号分割变量。
- 结构替换:大括号支持结构替换,具体有+、-、=、?几个符号具体如下方代码示例。
- 模式替换:大括号支持模式替换,具体有#、##、%、%%几个结构,具体如下方代码示例。
echo "------创建多个文件文件------"
touch {a,b,c,d}.txt
touch {1..5}.c
ls
echo "------创建代码块------"
#下方代码执行五件事:1.打印hello Shell 2.打印时间 3.展示目录 4.创建文件 5.输出重定向
{
echo "hello Shell"
date
ls
touch log.txt
} > log.txt
echo "------分割变量------"
val=Shell
echo "hello$val"
echo "$valhello"
echo "${val}hello"
#结构替换
#${val:-string}:当val为空,${val:-string}输出a,val不为空时,则输出val
val1=""
echo ${val1:-a1} "val1此时值是:$val1"
val2="hello ---"
echo ${val2:-a1} "val2此时值是:$val2"
echo -e "\n"
echo -e "\n"
echo -e "\n"
#${val:+string}:与-string相反,为空${val:+string}输出val, 不为空输出a2
val3=""
echo ${val3:+a2} "val3此时值是:$val3"
val4="hello +++"
echo ${val4:+a2} "val4此时值是:$val4"
echo -e "\n"
echo -e "\n"
echo -e "\n"
#${val:=string}:val为空时,${val:=string}输出为a,同时val的值也会被赋值为a,不为空则不作为
val5=""
echo ${val5:=a3} "val5此时值是:$val5"
val6="hello ==="
echo ${val6:=a3} "val6此时值是:$val6"
echo -e "\n"
echo -e "\n"
echo -e "\n"
#${val:?string}:val不为空则${val:=string}输出为val,val为空,则会将string输出到标准错误,并且退出脚本
val7="hello ???"
echo ${val7:?a4} "val7此时值是:$val7"
val8=""
echo ${val8:?a4} "val8此时值是:$val8"
echo "end-----"
之所以列的这么清楚,是希望大家能看清楚这几个结构替换的关系,-和+的操作上是对应的,不会修改val的值,但是=和?会修改,且它们在操作上目的不同,=只检查val是否为空,?不仅仅检测是否为空,而且会返回错误码。
当然stirng的位置不仅仅可以是string,同样可以替换其他变量或者命令。
#模式替换
#${val%pattern}:检测字符串中是否满足同一的模式结尾,如果是则删除右边最短的匹配模式
val1=helloshellhelloshellhelloshell
echo ${val1%s*}
echo -e "\n"
#${val%%pattern}:检测字符串中是否满足同一的模式结尾,是就删除右边最长的匹配模式
val2=helloshellhelloshellhelloshell
echo ${val2%%s*}
echo -e "\n"
#${val#pattern}:检测字符串中是否满足同一的模式结尾,是就删除左边边最短的匹配模式
val3=helloshellhelloshellhelloshell
echo ${val3#*s}
echo -e "\n"
#${val##pattern}:检测字符串中是否满足同一的模式结尾,是就删除左边边最长的匹配模式
val4=helloshellhelloshellhelloshell
echo ${val4##*s}
echo -e "\n"
8.重新认识Shell基本变量
讲到这里,其实对Shell大部分语法都了解了,在第二章节里我们简单介绍了Shell的内置变量,如今,我们再重新介绍它们,让大家有个不同的认识。
(一)基本变量
- $0:执行的文件名
- $1:脚本文件的第一个参数
- $#:传递到脚本的参数个数
- $*:以一个单字符串显示所有向脚本传递的参数
-
- $?:显示最后命令的退出状态,0表示没有错误,其它值表示有错误例子a.sh
- *类似,但是使用时要加引号,如"1,$2...的形式输出参数。
- $-:显示Shell使用的当前选项,和set类似
我相信,大家此时再看见这些符号就会熟悉很多了。
(二)常见通配符
- *:匹配0或者多个字符,如a*,那么aa,ab,acaaaa,等等都是符合的
- ?:匹配任意一个字符,如a?b,那么abb,anb等等都是符合的
- [list]:匹配列表内的一个字符,如a[xyz]b,那么只有axb,ayb,azb.
- [!list]:匹配一个不满足列表条件的字符,如a[!0-9]b,那么中间字符就不能是阿拉伯数字。
- {string1,string2,string3...}:匹配大括号内的一个字符串
尽管通配符看起来和正则表达式差不多,但是还是不同的,把通配符当作正常符号看就行了。
(三)常见元字符(特殊字符)
- IFS:由或或三者之一组成
- CR:
- =:变量赋值
- $:引用变量或者运算替换
- >:重定向至标准输出
- <:重定向至标准输入
剩下的一部分元字符已经再之前的章节里介绍了,就不再赘述。
(四)转义符
有的时候我们想让特殊符号单纯作为一个字符,就需要用到转义字符。
- '':单引号,其中的Shell元字符通配符都会被关掉,但是不允许在单引号内再出现单引号。
- "":双引号,其中只允许出现特定的Shell元字符--$和`
-