一、介绍
1. shell 介绍
Shell ⼀个命令解释器,它接收应⽤程序/⽤户命令,然后调⽤操作系统内核。
Shell还是⼀个功能强⼤的编程语⾔,易编写、易调试、灵活性强。
2.Linux提供的Shell解析器有
cat /etc/shells
3.bash 和 sh的关系
ll /bin/ | grep bash
4.Centos默认的Shell解析器是bash
echo $SHELL
二、定义
1.变量名的定义规则
- 变量名称可以由字⺟、数字和下划线组成,但是不能以数字开头,环境变量名建议⼤ 写。
- 等号两侧不能有空格
- 在bash中,变量默认类型都是字符串类型,⽆法直接进⾏数值运算。
- 变量的值如果有空格,需要使⽤双引号或单引号括起来。
2.等号周围没有空格
对于许多语⾔,例如 Python,在等号周围添加空格是⼀个好习惯,因为它可以提⾼代码的可读性。 但是在 Bash 中,不应该在定义变量时添加额外的空格。 如果声明⼀个变量 name,如下:
name = "Zhang"
这⾥会有⼀个错误:
-bash: name: command not found
如上所示,Bash 将 name 视为命令⽽不是变量,因为添加了不必要的空格。 因此,定义变量的正确⽅法如下:
name="Zhang"
3.正确地定义数组
在 Bash 中定义⼀个数组并不难。只需要使⽤⼀对括号来包含所有元素,如下例所示:
arr=("小王子" "小喵咪" "小丫丫")
俗话说得好,“细节决定成败"。之前在编写 Bash 脚本时犯了⼀个严重的错误。习惯性地使⽤逗号(⽽ ⾮空格)来分隔数组中的每个元素。
arr=("小王子" "小喵咪" "小丫丫")
echo ${arr[1]} #输出数组第一个
echo ${arr[*]} #输出数组全部
Bash 不会将逗号视为分隔符,并且在 arr 数组中只有⼀个元素小王子 小喵咪 小丫丫) ⽽不是预期的三个。
4. 查看所有的变量
set
5. 取消变量的设置
unset 变量名
6. 将局部环境变量提升为全局
export 变量名
7.正确选择引号
当在 Bash 中声明⼀个变量时,关于引号的使⽤有 3 个可选的⽅案:
- 没有引号
- ⽤单引号
- ⽤双引号
默认情况下,Bash 中的每个值都是⼀个字符串。因此,如果不需要空格,就不需要使⽤任何引号。(同 样,它与其他语⾔有些不同,在其他语⾔中,您不能在没有引号的情况下定义字符串) 当需要使⽤引号时,请注意单引号和双引号之间的区别。 例如,声明 3 个变量,如下所示。
总⽽⾔之,⼀对单引号内的字符串将始终被解释为它的本身。
8. 避免在命令中使⽤反引号
在 Bash 中,可以将命令的结果保存到变量中。有两种可能的⽅法来做到这⼀点: variable=`command`
variable=$(command)
例如,要保存 ls 命令的结果,可以这样写:
file_list=`ls` ===== file_list=$(ls)
但是,这⾥的最佳实践始终是使⽤第⼆种⽅法,尤其是在编写较⻓的脚本时。因为反引号和单引号看起 来很相似,有时可能会混淆它们。
9. 特殊的变量名
- $n(功能描述:n为数字,$0代表该脚本名称,$1-$9代表第⼀到第九个参数,⼗以上的参数需要 ⽤⼤括号包含,如${10})
- $# (功能描述:获取所有输⼊参数个数,常⽤于循环)。
- $* (功能描述:这个变量代表命令⾏中所有的参数,$*把所有的参数看成⼀个整体)
- $@ (功能描述:这个变量也代表命令⾏中所有的参数,不过$@把每个参数区分对待)
- $? (功能描述:最后⼀次执⾏的命令的返回状态。如果这个变量的值为0,证明上⼀个命令正 确执⾏;如果这个变量的值为⾮0(具体是哪个数,由命令⾃⼰来决定),则证明上⼀个命令执⾏ 不正确了。)
三、运算符
1. 算数运算符
(1)“$((运算式))”或“$[运算式]”
(2)expr + , - , \*, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
2. 逻辑运算符
格式:[ 条件 ] 注意:[] ⾥⾯前后必须要有空格
结果:0 表示真 ⾮0表示假
(1)两个整数之间⽐较 = 字符串⽐较
-lt ⼩于(less than)
-le ⼩于等于(less equal)
-eq 等于(equal)
-gt ⼤于(greater than)
-ge ⼤于等于(greater equal)
-ne 不等于(Not equal)
(2)按照⽂件权限进⾏判断
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执⾏的权限(execute)
(3)按照⽂件类型进⾏判断
-f ⽂件存在并且是⼀个常规的⽂件(file)
-e ⽂件存在(existence)
-d ⽂件存在并是⼀个⽬录(directory)
(4)多条件判断(&& 表示前⼀条命令执⾏成功时,才执⾏后⼀条命令,|| 表示上⼀条命令执⾏ 失败后,才执⾏下⼀条命令)
四、正则表达式
正则表达式使⽤单个字符串来描述、 匹配⼀系列符合某个语法规则的字符串。 在很多⽂本编辑器⾥, 正则表达式通常被⽤来检索、 替换那些符合某个模式的⽂本。 在 Linux 中, grep,sed, awk 等⽂本 处理⼯具都⽀持通过正则表达式进⾏模式匹配。
1. 常规匹配
例如下⾯的命,会对/etc/passwd的每⾏内容进⾏匹配,将含有root的⾏输出,如图中红⾊的部分即为匹 配的内容
[root@test001 ~]# cat /etc/passwd | grep root
2. 常⽤的特殊字符串
^匹配⼀⾏的开头,如下,会匹配/etc/passwd中以root开头的行
[root@test001 ~]# cat /etc/passwd | grep ^root
$匹配⼀⾏的结尾,如下,会匹配出/etc/passwd中以bash结尾的行
[root@test001 ~]# cat /etc/passwd | grep bash$
.匹配⼀个任意字符,如下,可以匹配含有四个字符,其中第1个字符是r,第4个字符是t的⾏,中间两个 可以是任意字符
[root@test001 ~]# cat /etc/passwd | grep r..t
*不单独使⽤,他和上⼀个字符连⽤,表示匹配上⼀个字符0次或多次,如下,可以匹配第1个字符是r, 最后1个字符是t,中间可以包含任意数量的o
[root@test001 ~]# cat /etc/passwd | grep ro*t
字符区间(中括号):[]表示匹配某个范围内的⼀个字符,例如
[root@test001 ~]# cat /etc/passwd | grep "[a-z]*"
\表示转义,并不会单独使⽤,由于所有特殊字符都有其特定的匹配模式,当匹配某⼀特殊字符本身时 (例如,我想找出所有包含‘$’的⾏),就会碰到困难,此时就要将转义字符和特殊字符连⽤,来表示特 殊字符本身,例如
[root@test001 ~]# echo "abc$" | grep "\\$"
abc$
[root@test001 ~]# echo "abc$" | grep '\$'
abc$
扩展的正则表达式 这⾥说⼀下,有些语⾔中⽀持正则表达式的扩展语法,如{n,m}等等,对于这种,使⽤grep匹配的时候, 需要添加-E选项,否则⽆法识别这种语法。 ⽐如下⾯2⾏,匹配a-z中的任意字符2或者3次
[root@test001 ~]# echo "ab,cdre" | grep "[a-z]{2,3}"
[root@test001 ~]# echo "ab,cdre" | grep -E "[a-z]{2,3}"
ab,cdre
五、条件选择、判断
1. 条件选择 if
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
用法格式:
#用法格式
if 判断条件 1 ; then
条件为真的分⽀代码
elif 判断条件 2 ; then
条件为真的分⽀代码
elif 判断条件 3 ; then
条件为真的分⽀代码
else
以上条件都为假的分⽀代码
fi
2. 条件判断 case
注意事项:
1) case⾏尾必须为单词“in”,每⼀个模式匹配必须以右括号“)”结束。
2) 双分号“;;”表示命令序列结束,相当于java中的break。
3) 最后的“*)”表示默认模式,相当于java中的default。
用法格式:
case $name in
PART1)
cmd
;;
PART2)
cmd
;;
*)
cmd
;;
esac
3. 循环(四种)
1. for
用法格式:
# ⽅式⼀
for name in 列表 ;do
循环体
done
# ⽅式⼆ 类似于C语⾔⻛格的语法
for (( 初始值; 条件表达式; 变量改变 )) ;do
cmd
done
2.while
用法格式:
while 循环控制条件 ;do
循环
done
3.until 循环
用法格式:
unitl 循环条件 ;do
循环
done
4. select 循环与菜单
select variable in list
do
循环体命令
done
① select 循环主要⽤于创建菜单,按数字顺序排列的示菜单项将显示在标准错误上,并显示PS3 提示 符,等待⽤户输⼊
② ⽤户输⼊菜单列表中的某个数字,执⾏相应的命令
③ ⽤户输⼊被保存在内置变量 REPLY 中
④ select 是个⽆限循环,因此要记住⽤ break 命令退出循环,或⽤ exit 按 命令终⽌脚本。也可以按 ctrl+c退出循环
⑤ select 和 经常和 case 联合使⽤
⑥ 与for循环类似,可以省略 in list, 此时使⽤位置参量
案例:
PS3="请输⼊你要选择的序号: "
select menu in ⽶饭 扯⾯ 包⼦ 稀饭 退出
do
case $REPLY in
1|4)
echo "$menu 价格是 15"
;;
2|3)
echo "$menu 价格是 20"
;;
5)
break
;;
*)
echo "请你好好选"
esac
done
4. read 读取控制台输⼊
语法:
read(选项)(参数)
: -p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数 变量:指定读取值的变量名
5.自定义函数
语法:
案例:
vim demo13.sh
function func()
{
local num=$1
if [ $num -lt 2 ]; then
return 1 # Numbers less than 2 are not prime
fi
for ((i=2; i*i<=num; i++));
do
if [[ $((num % i)) -eq 0 ]]; then
echo "$num 不是质数"
return 0
fi
done
echo "$num 是质数"
}
# Prompt user for input
read -p "请输入一个数字: " number
func $number
sh demo13.sh
注意:
(1)必须在调⽤函数地⽅之前,先声明函数,shell脚本是逐⾏运⾏。不会像其它语⾔⼀样先编 译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后⼀ 条命令运⾏结果,作为返回值。return后跟数值n(0-255)