Bootstrap

shell的基本操作

一、shell 介绍

 Shell ⼀个命令解释器,它接收应⽤程序/⽤户命令,然后调⽤操作系统内核。 Shell还是⼀个功能强⼤的编程语⾔,易编写、易调试、灵活性强。

二、基本语法定义

2.1. 变量名的定义规则

(1)变量名称可以由字⺟、数字和下划线组成,但是不能以数字开头,环境变量名建议⼤写。

(2)等号两侧不能有空格

(3)在bash中,变量默认类型都是字符串类型,⽆法直接进⾏数值运算。

(4)变量的值如果有空格,需要使⽤双引号或单引号括起来。

2.2. 等号周围没有空格

在 Bash 中,不应该在定义变量时添加额外的空格。

例:name="Zhang"

echo $name输出变量

2.3. 正确地定义数组 :只需要使⽤⼀对括号来包含所有元素。

例: names=("Zhang" "Elon" "Bill")

echo ${arr[1]} 获取数组的值

2.4. 查看所有的变量 set

2.5. 取消变量的设置 unset 变量名

2.6. 将局部环境变量提升为全局   export 变量名

2.7. 正确选择引号

当在 Bash 中声明⼀个变量时,关于引号的使⽤有 3 个可选的⽅案:

  1. 没有引号
  2. ⽤单引号
  3. ⽤双引号

 默认情况下,Bash 中的每个值都是⼀个字符串。因此,如果不需要空格,就不需要使⽤任何引号。(同样,它与其他语⾔有些不同,在其他语⾔中,您不能在没有引号的情况下定义字符串) 当需要使⽤引号时,请注意单引号和双引号之间的区别。

  1. ⼀对单引号内的字符串将始终被解释为它的本身。
  2. 而双引号内的字符串可以进行解析

#例:

DOG=金毛

D1=’${DOG}是小狗’    

D2=”${DOG}是小狗”

echo $D1

输出:${DOG}是小狗

echo $D2

输出:金毛是小狗

2.8. 避免在命令中使⽤反引号

在 Bash 中,可以将命令的结果保存到变量中。有两种可能的⽅法来做到这⼀点:

  1. variable=`command`
  2. variable=$(command)

 例如,要保存 ls 命令的结果,可以这样写:

  file_list=`ls` 或者file_list=$(ls)

但是,这⾥的最佳实践始终是使⽤第⼆种⽅法,尤其是在编写较⻓的脚本时。因为反引号和单引号看起来很相似,有时可能会混淆它们。

2.9. 特殊的变量名

2.9.1. $n

 $n(功能描述:n为数字,$0代表该脚本名称,$1-$9代表第⼀到第九个参数,⼗以上的参数需要⽤⼤括号包含,如${10})

sh demo01.sh a b

$0是脚本名字 $1,$2分别表示参数

 2.9.2. $#

 $# (功能描述:获取所有输⼊参数个数,常⽤于循环)。

2.9.3. $*

 $* (功能描述:这个变量代表命令⾏中所有的参数$*把所有的参数看成⼀个整体

2.9.4. $@

$@ (功能描述:这个变量也代表命令⾏中所有的参数,不过$@把每个参数区分对待

2.9.5. $?

$? (功能描述:最后⼀次执⾏的命令的返回状态。如果这个变量的值为0,证明上⼀个命令正确执⾏;如果这个变量的值为⾮0(具体是哪个数,由命令⾃⼰来决定),则证明上⼀个命令执⾏不正确了。)

三、运算符

3.1 算数运算符

(1)“ $((运算式))” 或“ $[运算式]”

(2)expr + , - , \*, /, % 加,减,乘,除,取余

 注意:expr运算符间要有空格

例:expr 3 + 2

3.2 逻辑运算符

格式:[ 条件 ] 注意:[] ⾥⾯前后必须要有空格

 结果:0 表示真 ⾮0表示假

(1)两个整数之间⽐较

  1. = 字符串⽐较
  2. -lt ⼩于(less than)
  3. -le ⼩于等于(less equal)
  4.  -eq 等于(equal)
  5. -ne 不等于(Not equal)
  6. -gt ⼤于(greater than)
  7. -ge ⼤于等于(greater equal)

#例:

[ 9 -lt 10 ]

echo $?

输出:0 表示真

(2)按照⽂件权限进⾏判断

  1. -r 有读的权限(read)
  2. -w 有写的权限(write)
  3. -x 有执⾏的权限(execute)

#例:

[ -r demo01.sh ]

echo $?

(3)按照⽂件类型进⾏判断

  1. -f ⽂件存在并且是⼀个常规的⽂件(file)
  2. -e ⽂件存在(existence)
  3.  -d ⽂件存在并是⼀个⽬录(directory)

(4)多条件判断&& 表示前⼀条命令执⾏成功时,才执⾏后⼀条命令,|| 表示上⼀条命令执⾏失败后,才执⾏下⼀条命令)

#例:

[ 9 -lt 10 ] && echo 对

输出    对

[ 9 -gt 10 ] && echo 对

无输出

 四、 正则表达式

 正则表达式使⽤单个字符串来描述、匹配⼀系列符合某个语法规则的字符串。 在很多⽂本编辑器⾥,正则表达式通常被⽤来检索、替换那些符合某个模式的⽂本。 在 Linux 中, grep,sed, awk 等⽂本处理⼯具都⽀持通过正则表达式进⾏模式匹配。

 4.1. 常规匹配

 例如下⾯的命令,会对/etc/passwd的每⾏内容进⾏匹配,将含有root的⾏输出,输出内容红⾊的部分即为匹配的内容

cat /etc/passwd | grep root

4.2. 常⽤的特殊字符串

4.2.1. 特殊字符:^

^匹配⼀⾏的开头,如下,会匹配/etc/passwd中以root开头的⾏

cat /etc/passwd | grep ^root

4.2.2. 特殊字符:$

$匹配⼀⾏的结尾,如下,会匹配出/etc/passwd中以bash结尾的⾏

cat /etc/passwd | grep bash$

4.2.3. 特殊字符:.

 .匹配⼀个任意字符,如下,可以匹配含有四个字符,其中第1个字符是r,第4个字符是t的⾏,中间两个 可以是任意字符

cat /etc/passwd | grep r..t

4.2.4. 特殊字符:*

*不单独使⽤,他和上⼀个字符连⽤,表示匹配上⼀个字符0次或多次,如下,可以匹配第1个字符是r, 最后1个字符是t,中间可以包含任意数量的o

cat /etc/passwd | grep ro*t

4.2.5. 字符区间(中括号):[]

[]表示匹配某个范围内的⼀个字符,例如

 [6,8]   匹配6或者8

 [0-9]  匹配1个0-9的数字

[0-9]*  匹配任意⻓度的数字字符串

[a-z]  匹配1个a-z之间的字符

[a-z]* 匹配任意⻓度的字⺟字符串

[a-ze-f]  匹配a-z或者e-f之间的任意⼀个字符

cat /etc/passwd | grep "[a-z]*"

4.2.6. 特殊字符:\

\表示转义,并不会单独使⽤,由于所有特殊字符都有其特定的匹配模式,当匹配某⼀特殊字符本身时 (例如,我想找出所有包含‘ $’ 的⾏),就会碰到困难,此时就要将转义字符和特殊字符连⽤,来表示特殊字符本身,例如

echo '123$54$5432' | grep '\$'

注:不能用双引号 因为双引号会转义掉$

扩展的正则表达式 :有些语⾔中⽀持正则表达式的扩展语法,需要添加-E选项,否则⽆法识别这种语法。

 ⽐如下⾯2⾏,匹配a-z中的任意字符2或者3次

echo "ab,cdre" | grep -E "[a-z]{2,3}"

五、条件选择、判断、循环

5.1. 条件选择 if

 注意事项:

(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格

(2)if后要有空格

#语法格式

if 判断条件 1 ; then

        条件为真的分⽀代码

elif 判断条件 2 ; then

        条件为真的分⽀代码

elif 判断条件 3 ; then

        条件为真的分⽀代码

else

        以上条件都为假的分⽀代码

 fi 

#例:

if [  $1 -lt  16 ]

then

     echo "娃还小"

else

     echo "娃长大了"

fi

5.2. 条件判断 case

#语法格式

case $name in

 PART1)

       cmd

         ;;

 PART2)

        cmd

         ;;

*)

        cmd

         ;;

esac

#例:

case $1 in

"上午")

        echo "火锅"

        echo "烤肉"    

        ;;

"中午")

        echo "3碗大米饭"

        echo "6个纯瘦夹馍"

        ;;

"晚上")

        echo "粥"

        echo "小甜水"

        ;;

*)

        echo "请填写正确的时间"

        ;;

esac

注意事项:

1) case⾏尾必须为单词“ in” ,每⼀个模式匹配必须以右括号“ )” 结束。

2) 双分号“ ;; ” 表示命令序列结束,相当于java中的break。

3) 最后的“ *)” 表示默认模式,相当于java中的default。

5.3. 循环(四种)

 5.3.1. for

#语法格式

# ⽅式⼀

 for name in 列表 ;do

        循环体

done

# ⽅式⼆ 类似于 C 语⾔⻛格的语法

for (( 初始值 ; 条件表达式 ; 变量改变 )) ;do

         cmd

done

#例:

#方式一

for j in $*

do

        echo $j

done

#方式二

s=0

for((i=0;i<=100;i++))

do

        s=$[$s+$i]

done

echo $s

#对$* 和 $@ 做对⽐:

for j in "$*"

do

        echo $j

done

for j in "$@"

do

        echo $j

done

$*最终会被" "解析为一个连续的字符串只有一个元素

$@最终会被" "解析为一个数组每个元素都是传入的参数

sh demo05.sh aa bb cc

输出结果如下:

aa bb cc

aa

bb

cc

5.3.2. while

#语法格式

while 循环控制条件 ;do

        循环

done

循环控制条件;进⼊循环之前,先做⼀次判断;每⼀次循环之后会再次做判断;条件为“ 执⾏⼀次循环;直到条件测试状态为“ false ” 终⽌循环

#例:

num=$1

s=0

while [ $num -ge 0 ]

do

        s=$[$num+$s]

        num=$[$num-1]

done

echo $s

 5.3.3. until 循环

#语法格式

unitl 循环条件 ;do

         循环

done

进⼊条件:循环条件为true ;退出条件:循环条件为false;刚好和while相反,所以不常⽤,⽤while就 ⾏。

#例:

num=$1

s=0

until [ $num -eq 0 ]

do

        s=$[$num+$s]

        num=$[$num-1]

done

echo $s

 5.3.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

分析: PS3 是 select 的提示符,⾃动⽣成菜单,选择5 break 退出循环。

5.4. 循环⾥的⼀些⽤法

 5.4.1. 循环控制语句

 语法:

continue :提前结束第N层的本轮循环,⽽直接进⼊下⼀轮判断;最内层为第1层

break :提前结束第N层循环,最内侧为第1层

#例:

while CONDTITON1; do

        CMD1

        if CONDITION2; then

                 continue / break

         fi

        CMD2

done

六、read 读取控制台输⼊

6.1. 语法

read(选项)(参数)

选项:

-p:指定读取值时的提示符;

 -t:指定读取值时等待的时间(秒)。

参数:

变量:指定读取值的变量名

#脚本:

read -p "请输入你的名字" -t 5 username

echo $username

sh demo01.sh

#脚本:

read -p "请输入第一个数:" num1

read -p "请输入第二个数:" num2

echo "$num1 加上 $num2 的结束是 $[$num1+$num2]"

七、 ⾃定义函数

# 语法:

[ function ] funname[()]

 {

       Action;

 [return int;]

 }

Funname

#例:

function func1()

{      

        read -p "请输入第一个数:" num1

        read -p "请输入第二个数:" num2

        echo "$num1 加上 $num2 的结束是 $[$num1+$num2]"

}

func1

 注意:

(1)必须在调⽤函数地⽅之前,先声明函数,shell脚本是逐⾏运⾏。不会像其它语⾔⼀样先编译。

(2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后⼀ 条命令运⾏结果,作为返回值。return后跟数值n(0-255)

#练习:编写⼀个函数来计算输⼊的是不是⼀个质数

function func2()

{

        isok=1

        for(( i=2 ; i<$1 ; i++))

        do

                if [ $[ $1 % $i] -eq  0 ]

                then

                        isok=0

                        break

                fi

        done

                if [ $isok -eq 1 ]

                then

                        echo "$1 是一个质数"   

                else

                        echo "$1 不是一个质数"

                fi

}

read -p "请输入一个数" num

func2 $num

;