Bootstrap

bash脚本编程

目录

一、bash基础特性

二、条件判断:if语句

练习

三、用户交互

示例

四、循环

1.for

练习

2.while

练习

3.until

练习

4.循环控制语句(用于循环体中)

5.创建死循环

6.while循环的特殊用法(遍历文件的每一行)

7.for循环的特殊格式

练习

五、条件判断:case语句

六、函数

练习

七、数组

1.数组元素的赋值

2.引用数组元素

3.数组的长度(数组中元素的个数)

4.数组切片

5.向数组中追加元素

6.删除数组中的某元素

7.关联数组

八、bash的字符串处理工具

1.字符串切片

2.基于模式取子串

3.查找替换

4.查找并删除

5.字符大小写转换

6.变量赋值

九、bash脚本编程用到的命令

1.mktemp

2.install

练习

回顾

参考资料

      过程式编程语言基本控制结构:顺序执行、选择执行、循环执行

一、bash基础特性

            命令行展开:~, {}

            命令别名:alias/unalias

            命令历史:history

            命令和路径补全:$PATH

            glob: *, ?, [], [^]

            快捷键:Ctrl+{a,e,l,c,u,k}

            命令hash:hash

二、条件判断:if语句

选择执行:

单分支:

      if CONDITION; then

            if-true

      fi

双分支:

if CONDITION; then

if-true

else

if-false

fi

多分支:

if CONDITION1; then

if-true

elif CONDITION2; then

if-ture

elif CONDITION3; then

if-ture

...

esle

all-false

fi

逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束

判断条件CONDITION就是命令 [ ] 或shell命令

      CONDITION:

            bash命令:

                  用命令的执行状态结果

                        成功:true

                       失败:flase

                  P.S. 成功或失败的意义:取决于用到的命令

      通常情况下脚本程序应当判断执行者是否符合条件

练习

用户键入文件路径,脚本来判断文件类型

      #!/bin/bash

      #

      read -p "Enter a file path:" filename

      if [ -z "$filename" ]; then

          echo "Usage:Enter a file path."

          exit 2

      fi

      if [ ! -e $filename ]; then

          echo "No such file."

          exit 3

      fi

      if [ -f $filename ]; then

          echo "A common file."

      elif [ -d $filename ]; then

          echo "A directory."

      elif [ -L $filename ]; then

          echo "A symbolic file."

      else

          echo "Other type."

      fi

            注意:if语句可嵌套

三、用户交互

      read [option]... [name ...]

            -p 'PROMPT'     提示信息

            -t TIMEOUT      等待超时( s )

      bash -n /path/to/some_script

            检测脚本中的语法错误

      bash -x /path/to/some_script

            调试执行

示例

      #!/bin/bash

      # Version: 0.0.1

      # Author: MageEdu

      # Description: read testing

 

      read -p "Enter a disk special file: " diskfile

      [ -z "$diskfile" ] && echo "Fool" && exit 1

 

      if fdisk -l | grep "^Disk $diskfile" &> /dev/null; then

          fdisk -l $diskfile

      else

          echo "Wrong disk special file."

          exit 2

      fi

四、循环

      循环:for, while, until

      循环体:要执行的代码;可能要执行n遍

                  进入条件:

                  退出条件:

1.for

      for 变量名  in 列表; do

            循环体

      done

P.S. 循环体通常会用到变量

执行机制:

依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束

示例:添加10个用户, user1-user10;密码同用户名

      #!/bin/bash

      #

      if [ ! $UID -eq 0 ]; then

          echo "Only root."

          exit 1

      fi

      for i in {1..10}; do

          if id user$i &> /dev/null; then

          echo "user$i exists."

          else

               useradd user$i

            if [ $? -eq 0 ]; then

                echo "user$i" | passwd --stdin user$i &> /dev/null

                  echo "Add user$i finished."

              fi

          fi

      done

            列表生成方式:

                  ①直接给出列表

                  ②整数列表:

                       (a) {start..end}

                       (b) $(seq [start [step]] end)

                  ③返回列表的命令

                       $(COMMAND)

                  ④glob

                  (b) 变量引用;

                       $@, $* 参数列表

示例:判断某路径下所有文件的类型

      #!/bin/bash

      #

      for file in $(ls /var); do

          if [ -f /var/$file ]; then

                  echo "Common file."

          elif [ -L /var/$file ]; then

                  echo "Symbolic file."

          elif [ -d /var/$file ]; then

                  echo "Directory."

          else

                  echo "Other type."

          fi

      done               

示例:统计出总共有多少种类型,每种类型有多少个

      #!/bin/bash

      #

      declare -i estab=0

      declare -i listen=0

      declare -i other=0

      for state in $( netstat -tan | grep "^tcp\>" | awk '{print $NF}'); do

          if [ "$state" == 'ESTABLISHED' ]; then

            let estab++

          elif [ "$state" == 'LISTEN' ]; then

            let listen++

          else

            let other++

          fi

      done

      echo "ESTABLISHED:$estab"

      echo "LISTEN:$listen"

      echo "Unkown:$other"

练习

①/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件

      分别读取每个文件,以K开头的文件输出为文件加stop,以S开头的文件输出为文件名加start

                  “K34filename stop”

                  “S66filename start”

for file in $(ls /etc/rc.d/rc3.d)

do

    if [[ $file =~ ^K.* ]]; then

          echo "$file stop"

    elif [[ $file =~ ^S.* ]]; then

          echo "$file start"

    fi

done

②写一个脚本,使用ping命令探测172.16.250.1-254之间的主机的在线状态      P.S. -c 指明次数   &>/dev/null

#!/bin/bash

#

net='172.16.250'

uphosts=0

downhosts=0

for i in {1..154};do

        ping -c 1 -w 1 ${net}.$i &> /dev/null

        if [ $? -eq 0 ] ;then

                echo "${net}.$i is up."

                let uphosts++

        else

                echo "${net}.$i is down."

                let downhosts++

        fi

done

echo "Up hosts: $uphosts."

echo "Down hosts: $downhosts."

2.while

while CONDITION; do

循环体

done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断

条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环

因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正

示例:求100以内所有正整数之和

      #!/bin/bash

      declare -i sum=0

      declare -i i=1

      while [ $i -le 100 ]; do

          let sum+=$i

          let i++

      done

      echo "Summary:$sum."

练习

      ①添加10个用户

#!/bin/bash

#

declare -i n=1

while [ $n -le 10 ];do

        id user$n &> /dev/null

        if [ $? -eq 0 ];then

                echo "user$n is exits."

        else

                useradd user$n &> /dev/null

                echo "user$n" | passwd --stdin user$n

                echo "user$n adds successfully!"

        fi

        let n++

done

②通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态

declare -i n=1

declare -i upnum=0 && downnum=0

while [ $n -le 254 ];do

        ping -c 1 -w 1 172.16.250.$n &> /dev/null

        if [ $? -eq 0 ];then

                echo "172.16.250.$n is up."

                let upnum++

        else

                echo "172.16.250.$n is down."

                let downnum++

        fi

        let n++

done

echo "upnum:$upnum"

echo "downnum:$downnum"

③打印九九乘法表 (分别使用for和while循环实现)

for j in {1..9};do

        for i in $(seq 1 $j);do

                echo -n -e  "${i}X${j}=$[$i*$j]\t"

                let i++

        done

        echo

done

declare -i j=1 && i=1

while [ $j -le 9 ];do

        while [ $i -le $j ];do

                echo -ne "${i}X${j}=$[$i*$j]\t"

                let i++

        done

        echo

        let j++

        let i=1

done

④利用RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大者和最小者

declare -i max=0 min=0 i=1

while [ $i -le 10 ];do

        rand=$RANDOM

        echo $rand

        if [ $i -eq 1 ];then

                max=$rand

                min=$rand

        fi

        if [ $max -lt $rand ];then

                max=$rand

        fi

        if [ $min -gt $rand ];then

                min=$rand

        fi

        let i++

done

echo "max=$max"

echo "min=$min"

3.until

      until CONDITION; do

            循环体

      done

      进入条件:false

      退出条件:true

练习

      ①求100以内所正整数之和

            #!/bin/bash

            #

            declare -i i=1

            declare -i sum=0

            until [ $i -gt 100 ]; do

                let sum+=$i

                let i++

            done

echo "Sum:$sum" 

②打印九九乘法表

declare -i j=1

declare -i i=1

until [ $j -gt 9 ]; do

                until [ $i -gt $j ]; do

                       echo -n -e "${i}X${j}=$[$i*$j]\t"

                   let i++

                   done

                   echo

                   let i=1

                   let j++

done

4.循环控制语句(用于循环体中)

①continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断

            while CONDTIITON1; do

                  CMD1

                  ...

                  if CONDITION2; then

                        continue

                  fi

                  CMDn

                  ...

            done

②break [N]:提前结束循环

            while CONDTIITON1; do

                  CMD1

                  ...

                  if CONDITION2; then

                        break

                  fi

                  CMDn

                  ...

            done

示例:求100以内所有偶数之和;要求循环遍历100以内的所正整数

            #!/bin/bash

            #

            declare -i i=0

            declare -i sum=0

until [ $i -gt 100 ]; do

                  let i++

if [ $[$i%2] -eq 1 ]; then

                       continue

fi

                        let sum+=$i

done

echo "Even sum:$sum"

5.创建死循环

      while true; do

            循环体

      done

      until false; do

            循环体

      done

示例:每隔3秒钟到系统上获取已经登录的用户的信息;如果docker登录了,则记录于日志中,并退出

      #!/bin/bash

      #

      read -p "Enter a user name:" username

      while true; do

          if who | grep "^$username" &> /dev/null; then

                  break

          fi

          sleep 3

      done

      echo "$username logged on." >> /tmp/user.log

      第二种实现:

      read -p "Enter a user name:" username

      until who | grep "^$username" &> /dev/null; do

          sleep 3

      done

      echo "$username logged on." >> /tmp/user.log

6.while循环的特殊用法(遍历文件的每一行)

      while read line; do

            循环体

      done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line

示例:找出其ID号为偶数的所有用户,显示其用户名及ID号

#!/bin/bash

            while read line;do

                  if [ $[`echo $line | cut -d:-f3` % 2] -eq 0 ];then

echo -e -n "username:`echo $line | cut -d:-f1`\t"

echo "uid:`echo $line | cut -d:-f3 `"

fi

done < /etc/passwd

7.for循环的特殊格式

      for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)); do

            循环体

      done

            控制变量初始化:仅在运行到循环代码段时执行一次;

            控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

示例:求100以内所正整数之和

      declare -i sum=0

      for ((i=1;i<=100;i++)); do

          let sum+=$i

      done

      echo "Sum:$sum."

示例:打印九九乘法表

      for((j=1;j<=9;j++));do

              for((i=1;i<=j;i++))do

                  echo -e -n "${i}X${j}=$[$i*$j]\t"

              done

              echo

      done

练习

写一个脚本,完成如下任务

      ①显示一个如下菜单:

     cpu) show cpu information;

     mem) show memory information;

     disk) show disk information;

     quit) quit

      ②提示用户选择选项

      ③显示用户选择的内容

      cat << EOF

      cpu) show cpu information;

      mem) show memory information;

      disk) show disk information;

      quit) quit

      ============================

      EOF

      read -p "Enter a option:" option

      while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do

          read -p "Wrong option, Enter again:" option

      done

      if [ "$option" == 'cpu' ]; then

          lscpu

      elif [ "$option" == 'mem' ]; then

          cat /proc/meminfo

      elif [ "$option" == 'disk' ]; then

          fdisk -l

      else

          echo "Quit"

          exit 0

      fi

五、条件判断:case语句

case 变量引用 in

PAT1)

     分支1

     ;;

PAT2)

     分支2

     ;;

...

*)

     默认分支

     ;;

esac

示例:用户选择,并显示完成后不退出脚本;而是提示用户继续选择显示其它内容;直到使用quit方始退出

#!/bin/bash

#

cat << EOF

cpu) show cpu information

mem) show memory information

disk) show disk information

quit) quit

============================

EOF

read -p "Enter a option:" option

until [ $option == "quit" ];do

while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ];do

read -p "Wrong option, enter again:" option

done

case "$option" in

cpu)

lscpu

;;

mem)

cat /proc/meminfo

;;

disk)

fdisk -l

;;

        *)

echo "Quit"

exit 0

        esac

        read -p "Enter a option:" option

done

    echo "Quit"

exit 0

      总结:until, while, for, case

六、函数

      function:函数

            过程式编程:代码重用

                  模块化编程

                  结构化编程

语法一:

            function f_name {

                  ...函数体...

            }

      语法二:

            f_name() {

                  ...函数体...

            }

      调用:函数只有被调用才会执行

            调用方式:给定函数名

                       函数名出现的地方,会被自动替换为函数代码

函数的生命周期:被调用时创建,返回时终止

      return命令返回自定义状态结果

            0:成功

            1-255:失败

示例:添加用户

            function adduser {

               if id $username &> /dev/null; then

                    echo "$username exists."

                    return 1

               else

                    useradd $username

                    [ $? -eq 0 ] && echo "Add $username finished." && return 0

               fi

            }

            for i in {1..10}; do

                username=myuser$i

                adduser

            done

练习

写一个服务脚本,完成如下要求

①脚本可接受参数:start, stop, restart, status

②如果参数非此四者之一,提示使用格式后报错退出

③如果是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”

            考虑:如果事先已经启动过一次,该如何处理?

④如果是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”

            考虑:如果事先已然停止过了,该如何处理?

⑤如果是restart,则先stop, 再start

            考虑:如果本来没有start,如何处理?

⑥如果是status, 则

如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running...”

            如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped...”

            其中:SCRIPT_NAME为当前脚本名

#!/bin/bash

#

#chkconfig:- 88 12

#description:test service script

#

program=$(basename $0)

lockfile=/var/lock/subsys/$program

start(){

     if [ -e $lockfile ];then

           echo "$program is already running."

           return 0

     else

           touch $lockfile

     [ $? -eq 0 ] && echo "starting $program finished."

     fi

}

stop(){

     if [ -e $lockfile ];then

           rm -rf $lockfile && echo "Stop $program OK."

     else

           echo "$program is stopped yet."

     fi

}

status(){

     if [ -e $lockfile ];then

           echo "$program is running."

     else

           echo "$program is stopped."

     fi

}

usage(){

     echo "Usage:$program { start | stop | restart | status }"

}

 

if [ $# -lt 1 ];then

     usage

     exit 1

fi

case $1 in

start)

     start

     ;;

stop)

     stop

     ;;

restart)

     stop

     start

     ;;

status)

     status

     ;;

*)

     usage

     ;;

esac

      函数返回值:

            函数的执行结果返回值:

                  ①使用echo或print命令进行输出

                  ② 函数体中调用命令的执行结果

            函数的退出状态码

                  ①默认取决于函数体中执行的最后一条命令的退出状态码

                  ②自定义退出状态码:

                             return

函数可以接受参数:

传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;例如“testfunc arg1 arg2 ...”

在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $#等特殊变量

示例:添加10个用户        

  #!/bin/bash

  #

  function adduser {

     if [ $# -lt 1 ]; then

              return 2

              # 2:no arguments

     fi

     if id $1 &> /dev/null; then

              echo "$1 exists."

              return 1

     else

              useradd $1

              [ $? -eq 0 ] && echo "Add $1 finished." && return 0

     fi

  }

  for i in {1..10}; do

      adduser myuser$i

  done

变量作用域:

本地变量:当前shell进程;为了执行脚本会启动专用的shell进程;因此,本地变量的作用范围是当前shell脚本程序文件

            局部变量:函数的生命周期;函数结束时变量被自动销毁

                  在函数中定义局部变量的方法:

                        local NAME=VALUE

函数递归:

                  函数直接或间接调用自身

示例:N!=N(n-1)(n-2)...1

n(n-1)! = n(n-1)(n-2)!

            #!/bin/bash

            #

            fact() {

                if [ $1 -eq 0 -o $1 -eq 1 ]; then

                       echo 1

                else

                       echo $[$1*$(fact $[$1-1])]

                fi

            }

            fact $1

示例:求n阶斐波那契数列

#!/bin/bash

#

fab() {

    if [ $1 -eq 1 ]; then

     echo 1

    elif [ $1 -eq 2 ]; then

     echo 1

    else

     echo $[$(fab $[$1-1])+$(fab $[$1-2])]

    fi

}

fab $1

示例:打印NN乘法表,使用函数实现

declare -i i=1 && j=1

mul(){

        until [ $j -gt $1 ];do

                until [ $i -gt $j ];do

                        echo -en "${i}X${j}=$[$i*$j]\t"

                        let i++

                done

                echo

                let i=1

                let j++

        done

}

mul $1

七、数组

      变量:存储单个元素的内存空间

      数组:存储多个元素的连续的内存空间

            数组名

            索引:编号从0开始,属于数值索引

                  P.S. 索引也可支持使用自定义的格式,而不仅仅是数值格式

                               bash的数组支持稀疏格式

                  引用数组中的元素:${ARRAY_NAME[INDEX]}

声明数组:

            declare -a ARRAY_NAME

            declare -A ARRAY_NAME:关联数组(又称键值列表)

1.数组元素的赋值

①一次只赋值一个元素

                        ARRAY_NAME[INDEX]=VALUE

                             weekdays[0]="Sunday"

                             weekdays[4]="Thursday"

②一次赋值全部元素:

                       ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)

③只赋值特定元素:

                       ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)

④read -a ARRAY

2.引用数组元素

      ①单个元素

${ARRAY_NAME[INDEX]}

      P.S. 省略[INDEX]表示引用下标为0的元素,花括号绝对不能漏

      ②所有元素

      ${ARRAY[@]},  ${ARRAY[*]}

3.数组的长度(数组中元素的个数)

${#ARRAY_NAME[*]},  ${#ARRAY_NAME[@]}

示例:生成10个随机数保存于数组中,并找出其最大值和最小值

      #!/bin/bash

declare -a rand

declare -i max=0 && min=32767

for i in {0..9};do

        rand[$i]=$RANDOM

        echo ${rand[$i]}

        [ ${rand[$i]} -gt $max ] && max=${rand[$i]}

        [ ${rand[$i]} -lt $min ] && min=${rand[$i]}

        let i++

done

echo "max=$max  min=$min"

写一个脚本 :

定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;要统计其下标为偶数的文件中的行数之和

declare -a files

files=(/var/log/*.log)

declare -i lines=0

for i in $(seq 0 2 $[${#files[*]}-1]);do

        let lines+=$(wc -l ${files[$i]}| cut -d' ' -f1)

done

echo "lines=$lines"

4.数组切片

${ARRAY[@]:offset:number}

offset:要跳过的元素个数

number:要取出的元素个数

取偏移量之后的所有元素:${ARRAY[@]:offset}

5.向数组中追加元素

                  ARRAY[${#ARRAY[*]}]

6.删除数组中的某元素

                  unset ARRAY[INDEX]

7.关联数组

                  declare -A ARRAY_NAME

                  ARRAY_NAME=([index_name1]='val1' [index_name2]='val2' ...)

练习:生成10个随机数,升序或降序排序

declare -a rand

declare -i t

for i in {0..9};do

        rand[$i]=$RANDOM

done

for((i=0;i<=9;i++))do

        for((j=i+1;j<=9;j++))do

                if [ ${rand[$i]} -gt ${rand[$j]} ];then

                        let t=${rand[$i]}

                        let rand[i]=${rand[$j]}

                        let rand[j]=t

                fi

        done

        echo "${rand[$i]}"

done

八、bash的字符串处理工具

1.字符串切片

      ${var:offset:number}

      取字符串的最右侧几个字符:${var:-lengh}

      注意:冒号后必须有一空白字符

2.基于模式取子串

${var#*word}:其中word可以是指定的任意字符;功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符之间的所有字符

${var##*word}:同上,不过,删除的是字符串开头至最后一次由word指定的字符之间的所有内容

file="/var/log/messages"

${file##*/}:messages

${var%word*}:其中word可以是指定的任意字符;功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符之间的所有字符

file="/var/log/messages"

${file%/*}:/var/log

${var%%word*}:删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符

示例:url=http://www.tudou.com:80

${url##*:}

${url%%:*}

3.查找替换

${var/pattern/substi}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substi替换之

${var//pattern/substi}:查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substi替换

${var/#pattern/substi}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substi替换之

${var/%pattern/substi}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substi替换之

     

4.查找并删除

${var/pattern}:查找var所表示的字符串中,删除第一次被pattern所匹配到的字符串

${var//pattern}

${var/#pattern}

${var/%pattern}

5.字符大小写转换

${var^^}:把var中的所有小写字母转换为大写

${var,,}:把var中的所有大写字母转换为小写

6.变量赋值

${var:-value}:如果var为空或未设置,那么返回value;否则,返回var的值

${var:=value}:如果var为空或未设置,那么返回value,并将value赋值给var;否则,返回var的值

${var:+value}:如果var不空,返回value

${var:?error_info}:如果var为空或未设置,那么返回error_info;否则,返回var的值

     

      为脚本程序使用配置文件:

            ①定义文本文件,每行定义“filename=value”

            ②在脚本中source此文件即可

九、bash脚本编程用到的命令

1.mktemp

mktemp [OPTION]... [TEMPLATE]

TEMPLATE:filename.XXX

XXX至少要出现三个

OPTION:

-d:创建临时目录

--tmpdir=/PATH/TO/SOMEDIR:指明临时文件目录位置

2.install

install [OPTION]... [-T] SOURCE DEST

install [OPTION]... SOURCE... DIRECTORY

install [OPTION]... -t DIRECTORY SOURCE...

install [OPTION]... -d DIRECTORY...

选项:

-m MODE

-o OWNER

-g GROUP

练习

写一个脚本

①提示用户输入一个可执行命令名称

②获取此命令所依赖到的所有库文件列表

③复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下

            /bin/bash ==> /mnt/sysroot/bin/bash

            /usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd

④复制此命令依赖到的所有库文件至目标目录下的对应路径下:

/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

            进一步地:

每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出

#!/bin/bash

declare -i lines=0

read -p "Please type a command name: " cmd

while [ -z $cmd ];do

        read -p "Please type a command name,again: " cmd

done

while [ $cmd != "quit" ];do

        install -d /test/sysroot/bin/$cmd

        cp /bin/$cmd /test/sysroot/bin/$cmd

        let lines=`ldd /bin/$cmd | wc -l | cut -d' ' -f1`

        for i in `seq 2 $lines`;do

                file=`ldd /bin/$cmd | head -"$i" | tail -1`

                file=${file#*/}

                file=${file%%(*}

                install -d /test/sysroot/$file

                cp /$file /test/sysroot/$file

        done

        echo "Copy the command-$cmd finished!"

        read -p "Please type a command name: " cmd

        while [ -z $cmd ];do

                read -p "Please type a command name,again: " cmd

        done

done

回顾

bash脚本编程

      编程语言:

                  数据结构

            顺序执行

            选择执行if, case

                  条件测试

                       运行命令或[[ EXPRESSION ]]

                             执行状态返回值

            循环执行for, while, until

                  将某代码段重复运行多次

                  重复运行多少次?

                       循环次数事先已知

                       循环次数事先未知

                       P.S. 必须有进入条件和退出条件

            函数:结构化编程及代码重用

                  function

——bash -n、bash -x

——if语句

            单分支:

                  if CONDITION; then

                       if-true

                  fi

            双分支:

                  if CONDITION; then

                       if-true

                  else

                       if-false

                  fi

            多分支:

                  if CONDITION1; then

                       if-true

                  elif CONDITION2; then

                       if-ture

                  elif CONDITION3; then

                       if-ture

                  ...

                  esle

                       all-false

                  fi

——case语句

            case 变量引用 in

            PAT1)

                  分支1

                  ;;

            PAT2)

                  分支2

                  ;;

            ...

            *)

                  分支n

                  ;;

            esac

case支持glob风格的通配符:

                  *:任意长度任意字符;

                  ?:任意单个字符;

                  []:指定范围内的任意单个字符;

                  a|b:a或b

——for循环

            for NAME in LIST; do

                  循环体

            done

——while循环

            while CONDITION; do

                  循环体

            done

    进入条件:CONDITION为true

    退出条件:false

——until循环

            until CONDITION; do

            循环体

            done

    进入条件:CONDITION为false

    退出条件:true

——函数:模块化编程

            function f_name {

                  ...函数体...

            }

            f_name() {

                  ...函数体...

            }

            return命令

            参数:

                  函数体中调用参数:$1, $2, ...

                  $*, $@, $#

            向函数传递参数:

                  函数名 参数列表

——数组

数组声明:declare -a

index:0-

关联数组:declare -A

——字符串处理

切片、查找替换、查找删除、变量赋值

参考资料:

马哥随堂笔记

注:诚恳欢迎读者对本文提出批评意见,若发现存在错误,我定第一时间修改。如果读者觉得文章对您有帮助,欢迎点赞鼓励一下哟٩(๑❛ᴗ❛๑)۶。

;