Linux入门——shell进阶

流程控制

顺序执行

If

单分支

if 判断条件;then    条件为真的分支代码fi  

双分支

if 判断条件;then
  条件为真的分支代码

else

  条件为假的分支代码
fi

多分支

  if 判断条件1; then
    条件为真的分支代码
  elif判断条件2; then
    条件为真的分支代码
  elif判断条件3; then
    条件为真的分支代码
  else
    以上条件都为假的分支代码
  fi

elif下同样可接else。表示第一个条件为真,第二条件为假的情况

根据命令的退出状态来执行命令

 if  echo $name|grep "$n" &> /dev/null ;then

选择执行

Case

case 变量引用in
  PAT1)分支1;;
  PAT2)分支2;;   #注意分支结束一定要能够用;;
  ...
  *)默认分支;;
esac

case支持glob风格的通配符:

  *: 任意长度任意字符

  ?: 任意单个字符

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

  a|b: a或b

循环执行

将某代码段重复运行多次

重复运行多少次:

循环次数事先已知

循环次数事先未知

有进入条件和退出条件

For

for 变量名in 列表;do
  循环体
done

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

例:利用for打印九九乘法表

#!/bin/bash
for a in {1..9} ;do
  b=$a
  for b in $(seq $b 9);do
    echo -n "$a*$b=$[$a*$b] "
  done
  echo
done

结果为

[[email protected] shell0]# ./99f.sh
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*6=36 6*7=42 6*8=48 6*9=54
7*7=49 7*8=56 7*9=63
8*8=64 8*9=72
9*9=81

While

while CONDITION; do
  循环体
done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环

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

进入条件:CONDITION为true

退出条件:CONDITION为false

例:利用while打印九九乘法表

#!/bin/bash
i=1
while [ $i -lt 10 ];do
  b=$i
  while [ $b -lt 10 ];do
    echo -n "$i*$b=$[$i*$b] "
    b=$[$b+1]
  done
  i=$[$i+1]
  echo
done

输出结果

[[email protected] shell0]# ./99w.sh
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*6=36 6*7=42 6*8=48 6*9=54
7*7=49 7*8=56 7*9=63
8*8=64 8*9=72
9*9=81

例:编写脚本/root/bin/copycmd.sh
  (1) 提示用户输入一个可执行命令名称
  (2) 获取此命令所依赖到的所有库文件列表
  (3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;如:/bin/bash ==> /mnt/sysroot/bin/bash        /usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd
  (4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
  (5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出

#!/bin/bash
echo "停止请输入quit"
while true;do  #永真循环
    read -p 请输入一个命令: cmd
    if [[ $cmd =~ quit ]];then #输入exit退出
        exit
    fi
    a=$(which $cmd| tail -1)  #查询命令来自哪个文件
    mkdir -p /app/sysroot$(echo $a|egrep -o "/.*/") &> /dev/null
    cp -v $a /app/sysroot/$a  #复制命令
    b=$(ldd /usr/bin/ls|cut ‘-d ‘ -f3)  #查询命令需要哪些库文件,这里有一个库文件是集成在内核里的不需要拷贝
    for n in $b;do
        if [ $n != ‘ ‘ ];then
            mkdir -p /app/sysroot$(echo $n|egrep -o "/.*/") &> /dev/null
             cp -v $n /app/sysroot$n  #复制库文件
        fi
    done
done

Until

与while完全一样只是判断条件不同

until CONDITION; do
  循环体
done

进入条件:CONDITION 为false

退出条件:CONDITION 为true

Select

select variable in list
do  case 变量引用in    PAT1)分支1;;    PAT2)分支2;;   #select 经常与case一起使用    ...    *)默认分支;;  esacdone

select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误

上,并显示PS3 提示符,等待用户输入

用户输入菜单列表中的某个数字,执行相应的命令

用户输入被保存在内置变量REPLY 中

循环控制语句

Continue

用于循环体中

continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层(不写默认为1)

Break

用于循环体中

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

Shift

shift [n]

用于将参量列表list 左移指定次数,缺省为左移一次。

参量列表list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到shift

函数

语法一:

  function f_name{

    ...函数体...

  }

语法二:

  function f_name(){

    ...函数体...

  }

语法三:

  f_name(){

    ...

  }

数组

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

数组:存储多个元素的连续的内存空间,相当于多个变量的集合

数组名和索引

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

注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本之后开始支持

bash的数组支持稀疏格式(索引不连续)

声明数组:

declare -a ARRAY_NAME

declare -A ARRAY_NAME: 关联数组

注意:两者不可相

例:1

为某餐馆用Shell制作一个点菜系统。功能如下:执行脚本会列出主菜单,如下

请选择您要吃的菜品

(消费满80打8折)

1)饭      2)面、

3)饺子  4)结账

等待用户选择
如选择1,则再问                  如选择2,则再问                               如选择3,则再问                                    如选择4,则直接退出
1)炒饭 10元                       1)炒面 10元                                     1)猪肉大葱 18元
2)盖饭 10元                       2)热干面 9元                                    2)素三鲜 15元
3)拌饭 12元                       3)烩面 15元                                      3)韭菜鸡蛋 18元
4)返回主菜单                     4)重庆小面 9元                                4)返回主菜单
                                            5)返回主菜单
选择后,提示用户,再吃几份,输入完后提示是否还要继续选,如继续选,则返回主菜单,然后继续以上过程,如不要继续选,则会打印消费单后退出,消费单格式如下

炒饭 5份 50元
热干面 1份 9元
素三鲜 1份 15元
总计 74元
折后 59.2元

#!/bin/bash
PS3=请您点餐:   #定义select的输入格式
echo "消费满80打8折,亲!"
declare -a fen                                                  #定义份数数组
caidan=(炒饭 盖饭 拌饭 炒面 热干面 烩面 小面 猪肉大葱 素三鲜 韭菜鸡蛋)  #定义菜单名数组
danjia=(10 10 12 10 9 15 9 18 15 18)                           #定义价格数组
while true ;do                              #定义永真循环方便循环跳出
  select variable in 饭 面 饺子 不吃滚蛋 结账                   #select列表,主菜单
  do
    case $REPLY in                                         #定义饭子菜单
      1)select riable in 炒饭 盖饭 拌饭 返回               
      do
        case $REPLY in
          1)echo "炒饭10元每份"
           read -p 您要几份: fen[0]        
           break 2;;                                 #跳出两层循环回到主菜单
          2)echo "盖饭10元每份"
           read -p 您要几份: fen[1]
           break 2;;
          3)echo "拌饭10元每份"
           read -p 您要几份: fen[2]
           break 2;;
          4)break 2;;
        esac
      done;;
      2)select riable in 炒面 热干面 烩面 小面 返回            #定义面子菜单
      do
        case $REPLY in
          1)echo "炒面10元份"
           read -p 您要几份: fen[3]
           break 2;;
          2)echo "热干面9元每份"
           read -p 您要几份: fen[4]
           break 2;;
          3)echo "烩面15元每份"
           read -p 您要几份: fen[5]
           break 2;;
          4)echo "小面9元每份"
           read -p 您要几份: fen[6]
           break 2;;
          5)break 2;;
        esac
      done;;
      3)select riable in 猪肉大葱 素三鲜 韭菜鸡蛋 返回                   #定义饺子子菜单
      do
        case $REPLY in
          1)echo "猪肉大葱18元每份"
           read -p 您要几份: fen[7]
           break 2;;
          2)echo "素三鲜15元每份"
           read -p 您要几份: fen[8]
           break 2;;
          3)echo "韭菜鸡蛋18元每份"
           read -p 您要几份: fen[9]
           break 2;;
          4)break 2;;
        esac
      done;;
      4)exit;;                                              #退出菜单
      5)echo "清单";a=0                                       #清单
       for ((i=0;i<10;i++));do
        if [ "${fen[$i]}" != "" ];then                      #判断fen[$i]是否非空,非空则证明点了该菜 
          echo "${caidan[$i]} ${danjia[$i]}/份 $[${fen[$i]}*${danjia[$i]}]元"
          a=$[$a+$[${fen[$i]}*${danjia[$i]}]]
        fi
       done
       echo "总计: $a"
       if [ $a -ge 80 ];then                               #判断是否打折
        echo "折后: $[$a*8/10]"
       else
        echo "折后: $[a]"
       fi
       exit;;
    esac

  done
done

例2:

写一个创建用户的脚本,要求如下
1.执行时会询问,请输入要创建的用户名称(当用户超时8秒不输入,提示超时并退出),脚本会检测用户名是否已经存在,若已存在,则提示用户已存在,是否要为其设置密码,如否,则继续回到第1步,询问用户另一个用户名。如是,进入第3步。
2.如第1步完成,则会创建指定用户,然后脚本继续问用户是否为新用户设置密码,如否,则返回第1步继续创建其他用户,如是,则进入第3步
3.为用户设置密码,要求密码要验证2次,2次一致才可通过。同时密码要满足复杂性要求,要求如下:
密码至少8个字符长度,密码必须包含 大写,小写字母,数字,和#@!,._ 这之中的三种字符。 如不满足,则提示用户密码太短或太简单,返回第3步。
且密码不能是 /usr/share/dict/words 已存在的字符,或是,则提示用户密码是个常见单词,然后返回第3步。
用户只能尝试设置新密码3次,若超过3次仍然没有设置出满足要求的密码,则直接返回第1步。
4.在任何步骤,只要输入exit均可退出脚本

#!/bin/bash
while true;do
    read -p "请输入用户名:" name
    a=$(cat /etc/passwd |cut -d: -f1)
    for n in $a;do                                                              #判断用户名是否合法
        if  echo $name|grep "$n" &> /dev/null ;then
            echo "用户名不合法"
            continue 2
        elif echo "$name" |egrep "[[:upper:]].{4,}";then
            true
            break 2
        else
            echo "请输入首字母大写且高于5位的字符"
            continue 2
        fi
    done
done
while true;do                                                                 #判断性别是否合法
    read -p "请输入性别male/female:" male
    case $male in
        male|female)break 2;;
        *)echo "输入错误请重新输入";continue 2;;
    esac
done
while true ;do                                                               #判断生日是否合法
    read -p "请输入生日例YYYY-MM-DD:" bir
    if echo $bir|egrep "[[:digit:]]{4}(-[[:digit:]]{1,2}){2}" &> /dev/null;then
        true
    else
        echo "输入不合法";continue 2
    fi
        bird=$(echo $bir|cut -d‘-‘ -f3)
        birm=$(echo $bir|cut -d‘-‘ -f2)
        biry=$(echo $bir|cut -d‘-‘ -f1)
    if cal $bird $birm $biry &> /dev/null;then
        break 2
    else
        echo "输入不合法";continue 2
    fi
done
while true;do                                                                #判断手机号是否合法
    read -p "请输入手机号:" ph
    if echo $ph |egrep ‘\<1[3857][[:digit:]]{9}\>‘ &> /dev/null;then
        break
    else
        echo "格式不对"
        continue
    fi
done
while true;do                                                          #判断身份证号是否合法
    read -p "请输入身份证号:" card
    echo $id |egrep ‘[[:digit:]]{17}[[:digit:]x]‘ &> /dev/null
        if [ $? -eq 0 ];then
                biry1=`echo $id |cut -c 7-10`
                birm1=`echo $id |cut -c 11-12`
                bird1=`echo $id |cut -c 13-14`
                if [ $(echo -n $birm|wc -m) -eq 1 ];then
                        birm=0$birm
                fi
                if [ $(echo -n $bird|wc -m) -eq 1 ];then
                        birm=0$bird

                fi
                if [ "$biry$birm$bird" == $biry1$birm1$bird1 ];then
                        shu=$[$(echo $id|cut -c 17)%2]
                        case $shu in
                                1)xingbie=male
                                if [ "$xingbie" != "$sex" ];then
                                        echo "性别错了"
                                        continue
                                else
                                        break
                                fi;;
                                *)xingbie=female
                                if [ "$xingbie" != "$sex" ];then
                                        echo "性别错了"
                                        continue
                                else
                                        break
                                fi;;
                        esac

                else
                        echo "日期不符"
                        continue
                fi
        else
                echo 格式不对
                continue
        fi
done
echo $name:$male:$dete:$card >> /root/info.txt

例3:

1.执行时会询问,请输入要创建的用户名称(当用户超时8秒不输入,提示超时并退出),脚本会检测用户名是否已经存在,若已存在,则提示用户已存在,是否要为其设置密码,如否,则继续回到第1步,询问用户另一个用户名。如是,进入第3步。
2.如第1步完成,则会创建指定用户,然后脚本继续问用户是否为新用户设置密码,如否,则返回第1步继续创建其他用户,如是,则进入第3步
3.为用户设置密码,要求密码要验证2次,2次一致才可通过。同时密码要满足复杂性要求,要求如下:
密码至少8个字符长度,密码必须包含 大写,小写字母,数字,和#@!,._ 这之中的三种字符。 如不满足,则提示用户密码太短或太简单,返回第3步。
且密码不能是 /usr/share/dict/words 已存在的字符,或是,则提示用户密码是个常见单词,然后返回第3步。
用户只能尝试设置新密码3次,若超过3次仍然没有设置出满足要求的密码,则直接返回第1步。
4.在任何步骤,只要输入exit均可退出脚本

#!/bin/bash
password() {                                        #函数判断密码的合法性
for ((i=0;i<=2;i++));do
    b=0
    read -p "请输入密码:" pass
    read -p "请确认密码:" rpass
    if echo $pass|grep [a-z] &> /dev/null;then
        b=$[$b+1]
    fi
    if echo $pass|grep [A-Z] &> /dev/null;then
         b=$[$b+1]
    fi
    if echo $pass|grep [\~\!\@\#\$\%\^\&\*] &> /dev/null;then
        b=$[$b+1]
    fi
    if echo $pass|grep [0-9] &> /dev/null;then
        b=$[$b+1]
    fi
    lens=$(echo $pass |grep -o .|wc -l)
    if [ "$pass" != "$rpass" ];then
         echo "两次密码不一致"
    elif [ $lens -lt 8 ];then
        echo "密码太短"
        echo "密码位数至少为8位"
    elif [ $b -lt 3 ];then
        echo "密码太过简单"
        echo "密码至少由大写,小写字母,数字,和特殊字符这之中的三种字符"
    elif cat /usr/share/dict/words | grep ".*$pass.*" &> /dev/null;then     #写的有点问题,应该用字典过滤密码,不是用密码过滤字典
        echo "密码中包含常用单词"
    else
        echo $pass |passwd --stdin $username &> /dev/null
        echo "密码修改成功"
        exit
    fi
done
}
while true ;do
read -p "请输入用户名:" -t 8 username                                     #超时输入则退出
a=$(echo $?)
if [ $a != 0 ];then
    echo
    echo "超时";exit
fi
if [ $username == exit ];then
    exit                                                           #输入exit退出
fi
if id $username &> /dev/null ;then
    echo "该用户已存在"
    read -p "是否为其设置密码y/n:" b
    case $b in
        y|Y)password "$username";;                                #调用passwd函数
        n|N)continue;;
        exit) exit;;                                             #输入exit退出
    esac
else
    useradd $username
    read -p "是否为新用户设置密码y/n:" c
    case $c in
          y|Y)password "$username";;
          n|N)continue;;
          exit) exit;;
      esac

fi

附:

eval命令

eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描

创建临时文件

mktemp命令:创建并显示临时文件,可避免冲突

mktemp[OPTION]... [TEMPLATE]

TEMPLATE: filename.XXX

X至少要出现三个

OPTION:

-d: 创建临时目录

-p DIR或--tmpdir=DIR:指明临时文件所存放目录位置

示例:

mktemp/tmp/test.XXX

tmpdir=`mktemp–d /tmp/testdir.XXX`

mktemp--tmpdir=/testdirtest.XXXXXX

安装复制文件

install命令:

install [OPTION]... [-T] SOURCE DEST 单文件

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

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

install [OPTION]... -d DIRECTORY...创建空目录

选项:

-m MODE,默认755

-o OWNER

-g GROUP

示例:

install -m 700 -o wang -g admins srcfile desfile

install –m –d /testdir/installdir

原文地址:https://www.cnblogs.com/angge/p/9469669.html

时间: 2024-08-09 23:32:46

Linux入门——shell进阶的相关文章

Linux入门-shell使用技巧

tab 命令补全 history 先前输入的命令,!+序号重新执行 ctrl+l,clear 清屏 ctrl+u 删除当前输入 ctrl+c 终止命令 ctrl+d 退出系统 一.命名别名 #alias 查看已有的别名 #alias copy=cp 让copy可以执行cp的命令 #unalias copy  删除别名 二.输入/输出重定向 0:标准输入(一般是键盘) 1:标准输出(一般是显示器) 2:标准错误输出(一般是显示器) #ls -l /home > /home/ab.txt 输出到ab

&lt;LINUX &gt;bash shell 入门 --linux学习笔记

首先说下我个人对于shell的理解,我觉得shell是一种通过各种控制语句将linux命令进行集合实现批处理的一种脚本语言. shell编程入门其实很简单,语法知识并不多,但是高级shell编程就很难,因为shell是用户和linux之间的桥梁,要编写高质量的shell脚本,就需要用户对linux有很全面的认识. 这里我们只分析shell脚本的语法知识,如想透彻的学习linux还需多努力. shell结构       1.#!指定执行脚本的shell 2.#注释行 3.命令和控制结构 创建she

Linux运维高薪入门及进阶全新经典视频-老男孩Linux(免费)

2015年5月21日最新发布,老男孩老师亲讲,全新Linux运维入门经典! 超级难得的linux经典企业级入门实战课程 价格:免费 数量:138节 本linux高薪运维入门及进阶,为入门教学中的基础部分,以简单.易用.高效的方式为初学者讲解如何学好LINUX的核心学习思想,讲解计算机硬件知识,基础命令,Linux基础知识及企业应用场景如何利用硬件优化服务,清晰透彻,超细讲解,适合0基础朋友学习或者相关岗位例如和It打交道的销售,编辑等做为了解linux的入口,也将十分有益!全民互联网时代开始了,

Linux Bash Shell编程快速入门

BASH 的基本语法 最简单的例子 -- Hello World! 关于输入.输出和错误输出 BASH 中对变量的规定(与 C 语言的异同) BASH 中的基本流程控制语法 函数的使用 2.1     最简单的例子 -- Hello World! 几乎所有的讲解编程的书给读者的第一个例子都是 Hello World 程序,那么我们今天也就从这个例子出发,来逐步了解 BASH. 用 vi 编辑器编辑一个 hello 文件如下: #!/bin/bash# This is a very simple

Linux Bash Shell入门教程

BASH 的基本语法 最简单的例子 -- Hello World! 关于输入.输出和错误输出 BASH 中对变量的规定(与 C 语言的异同) BASH 中的基本流程控制语法 函数的使用 2.1     最简单的例子 -- Hello World! 几乎所有的讲解编程的书给读者的第一个例子都是 Hello World 程序,那么我们今天也就从这个例子出发,来逐步了解 BASH. 用 vi 编辑器编辑一个 hello 文件如下: #!/bin/bash # This is a very simple

服务端工程师入门与进阶 Java 版

前言 欢迎加入我们.这是一份针对实习生/毕业生的服务端开发入门与进阶指南.遇到问题及时问你的 mentor 或者直接问我. 建议: 尽量用google查找技术资料. 有问题在stackoverflow找找,大部分都已经有人回答. 多看官方的技术文档. ibm developerworkers的文章质量整体上有保障. 平时花一些时间在github上阅读优秀项目源码. 入门(1-2 个月) 目标:参与简单的项目开发. 技能: 掌握 Java.经典的<Java 核心技术:卷1 基础知识>(或者<

linux学习-----shell基础

shell基础 1.什么是shell shell是一个C语言开发的程序 他是用户使用linux的桥梁 既是一个命令语言 一种应用程序 这个应用程序提供了一个界面 用户通过这个界面访问操作系统内核的服务 又是一种程序设计语言 2.什么是脚本 脚本就是一条条的文字命令 这些命令是可以看得到的 常见脚本 JS   PHP JSP   SQL    PHTHON PERL    SHELL  RUBY  JAVAFX 3.shell的优点: linux内置的脚本 程序开发效率高(批处理) 语法简单易学

linux入门系列20--Web服务之LNMP架构实战

作为本入门系列最后一篇文章,将演示如何在CentOS7环境下搭建LNMP环境来构建个人博客网站. 常见搭建网站的方式有LAMP.LNMP.IIS.Nginx.Tomcat等等,本文演示比较流行的基于LNMP方式来搭建动态WEB网站. 正如前文"linux入门系列6--软件包管理之rpm和yum仓库"所述,在Linux上安装软件通常有几种方式:通过编译源码安装.通过RPM安装.通过YUM仓库安装.截至目前,前面的文章都是通过yum或rpm方式进行安装,本文演示通过源码包方式进行安装. 一

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024