Shell ⼀个命令解释器,它接收应⽤程序/⽤户命令,然后调⽤操作系统内核。 Shell还是⼀个功能强⼤的编程语⾔,易编写、易调试、灵活性强。
对于许多语⾔,例如 Python,在等号周围添加空格是⼀个好习惯,因为它可以提⾼代码的可读性。 但是在 Bash 中,不应该在定义变量时添加额外的空格。如下示例:
name="小美" #正确 name = "小美" #错误 [root@iZ2zeh6vyxsq620zifz8jaZ~]# username="小 美" #引号内可加空格 [root@iZ2zeh6vyxsq620zifz8jaZ]#echo $username 小 美
在 Bash 中定义⼀个数组并不难。只需要使⽤⼀对括号来包含所有元素。如下示例:
注意:分隔数组中每个元素用空格!!!
arr=("陈少熙" "何浩楠" "王一珩") #等号两边不要空格,字符串之间要用空格分隔 #遍历数组 [root@iZ2zeh6vyxsq620zifz8jaZ ~]# arr=("陈少熙" "何浩楠" "王一珩") [root@iZ2zeh6vyxsq620zifz8jaZ ~]# echo $arr 陈少熙 [root@iZ2zeh6vyxsq620zifz8jaz ~]# echo ${arr[1]} "何浩楠" [root@iZ2zeh6vyxsq620zifz8jaZ ~]# echo ${arr[2]} "王一珩" [root@iZ2zeh6vyxsq620zifz8jaZ ~]# echo ${arr[3 ]} [root@iZ2zeh6vyxsq620zifz8jaZ ~]# echo ${arr[*]} 陈少熙 "何浩楠" "王一珩"
set #查看所有变量名
set #查看所有变量名 set username
unset 变量名 #删除环境变量
unset username #取消变量名的设置
export 变量名
当在 Bash 中声明⼀个变量时,关于引号的使⽤有 3 个可选的⽅案:
- 没有引号
- ⽤单引号
- ⽤双引号
默认情况下,Bash 中的每个值都是⼀个字符串。因此,如果不需要空格,就不需要使⽤任何引号。(同 样,它与其他语⾔有些不同,在其他语⾔中,您不能在没有引号的情况下定义字符串)。
当需要使⽤引号时,请注意单引号和双引号之间的区别。如下示例。
在 Bash 中,可以将命令的结果保存到变量中。如下保存命令方法:
file_list=`ls`
file_list=$(ls)
但是,这⾥的最佳实践始终是使⽤第⼆种⽅法,尤其是在编写较⻓的脚本时。因为反引号和单引号看起 来很相似,有时可能会混淆它们。
$n(功能描述:n为数字,$0代表该脚本名称,$1-$9代表第⼀到第九个参数,⼗以上的参数需要 ⽤⼤括号包含,如${10})
$# (功能描述:获取所有输⼊参数个数,常⽤于循环)。
$* (功能描述:这个变量代表命令⾏中所有的参数,$*把所有的参数看成⼀个整体)
$@ (功能描述:这个变量也代表命令⾏中所有的参数,不过$@把每个参数区分对待)
$? (功能描述:最后⼀次执⾏的命令的返回状态。如果这个变量的值为0,证明上⼀个命令正 确执⾏;如果这个变量的值为⾮0(具体是哪个数,由命令⾃⼰来决定),则证明上⼀个命令执⾏ 不正确了。)
(1)“ $((运算式)) ” 或 “ $[运算式] ”
(2)expr + , - , \*, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
格式:[ 条件 ] 注意:[] ⾥⾯前后必须要有空格
结果:0 表示真 ⾮0表示假
- = 字符串⽐较 -lt ⼩于(less than)
- -le ⼩于等于(less equal)
- -eq 等于(equal)
- -gt ⼤于(greater than)
- -ge ⼤于等于(greater equal)
- -ne 不等于(Not equal)
- -r 有读的权限(read)
- -w 有写的权限(write)
- -x 有执⾏的权限(execute)
- -f ⽂件存在并且是⼀个常规的⽂件(file)
- -e ⽂件存在(existence)
- -d ⽂件存在并是⼀个⽬录(directory)
- && 表示前⼀条命令执⾏成功时,才执⾏后⼀条命令
- || 表示上⼀条命令执⾏ 失败后,才执⾏下⼀条命令
正则表达式使⽤单个字符串来描述、 匹配⼀系列符合某个语法规则的字符串。 在很多⽂本编辑器⾥,正则表达式通常被⽤来检索、 替换那些符合某个模式的⽂本。 在 Linux 中, grep,sed, awk 等⽂本 处理⼯具都⽀持通过正则表达式进⾏模式匹配。
例如下⾯的命,会对/etc/passwd的每⾏内容进⾏匹配,将含有root的⾏输出
[root@test001 ~]# cat /etc/passwd | grep root
^ 匹配⼀⾏的开头,如下,会匹配/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
[] 表示匹配某个范围内的⼀个字符,例如
[6,8] | 匹配6或者8 |
[0-9] | 匹配1个0-9的数字 |
[0-9]* | 匹配任意⻓度的数字字符串 |
[a-z] | 匹配1个a-z之间的字符 |
[a-z]* | 匹配任意⻓度的字⺟字符串 |
[a-ce-f] | 匹配a-z或者e-f之间的任意⼀个字符 |
[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)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
if 判断条件 1 ; then 条件为真的分⽀代码 elif 判断条件 2 ; then 条件为真的分⽀代码 elif 判断条件 3 ; then 条件为真的分⽀代码 else 以上条件都为假的分⽀代码 fi
练习:写⼀个脚本传⼊⼀个分数参数 判断是如果⼤于90输出优秀,如果⼤于70输出优良,如果⼤于60 输出及格,如果⼩于60输出挨打
echo "请输入分数:" read score if [ $score -gt 90 ]; then echo "优秀" elif [ $score -gt 70 ];then echo "优良" elif [ $score -gt 60 ];then echo "及格" else echo "挨打" fi
注意事项:
1) case⾏尾必须为单词“in”,每⼀个模式匹配必须以右括号“)”结束。
2) 双分号“;;”表示命令序列结束,相当于java中的break。
3) 最后的“*)”表示默认模式,相当于java中的default。
case $name in PART1) cmd ;; PART2) cmd ;; *) cmd ;; esac
# ⽅式⼀ for name in 列表 ;do 循环体 done # ⽅式⼆ 类似于C语⾔⻛格的语法 for (( 初始值; 条件表达式; 变量改变 )) ;do cmd done
练习:做⼀个100以内的累加并输出结果
sum=0 for i in {1..100}; do sum=$((sum + i)) done echo "1 到 100 的累加结果为: $sum"
对上⾯的$* 和 $@ 做对⽐
while 循环控制条件 ;do 循环 done
循环控制条件;进⼊循环之前,先做⼀次判断;每⼀次循环之后会再次做判断;条件为“ true ” ,则 执⾏⼀次循环;直到条件测试状态为“ false ” 终⽌循环
unitl 循环条件 ;do 循环 done
进⼊条件:循环条件为true ;退出条件:循环条件为false;刚好和while相反,所以不常⽤,⽤while就 ⾏
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
分析: PS3 是 select 的提示符,⾃动⽣成菜单,选择5 break 退出循环。
continue :提前结束第N层的本轮循环,⽽直接进⼊下⼀轮判断;最内层为第1层 break :提前结 束第N层循环,最内侧为第1层
# 例: while CONDTITON1; do CMD1 if CONDITION2; then continue / break fi CMD2 done
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量 ==> 指定读取值的变量名
[ function ] funname[()] { Action; [return int;] } funname
注意:
(1)必须在调⽤函数地⽅之前,先声明函数,shell脚本是逐⾏运⾏。不会像其它语⾔⼀样先编 译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后⼀ 条命令运⾏结果,作为返回值。return后跟数值n(0-255)
#!/bin/bash function sum() { s=0 s=$[$1 + $2] echo $s } read -p "请输⼊第⼀个数" NUM1 read -p "请输⼊第⼆个数" NUM2 sum $NUM1 $NUM2
练习:编写⼀个函数来计算输⼊的是不是⼀个质数
function zhi() { num=$1 isok=1 for((i=2; i<$num; i++)) do if [ $[$num % $i ] -eq 0];then isok=0 break fi done if [ $isok -eq 1 ] then echo "$1是一个质数" else echo "$1不是质数" fi } read -p "请输入一个数" NUM1 zhi $NUM1