当前位置: 首页 > news >正文

C高级——shell(3)

一、shell的选择结构

        1.回顾:C语言的选择结构:if , if else if ,if else,switch (switch的执行速度最快)

        2.shell的选择结构: 单分支if 双分支 if else 多分支if elif case..in

  1.1 shell的选择结构的格式

--------C语言的格式------
单分支
    if(表达式)
    {
        C语句    
    }
双分支
    if(表达式)
    {
        C语句1    
    }
    else
    {
        C语句2    
    }
多分支
    if(表达式1)
    {
        C语句1            
    }
    else if(表达式2)
    {
        C语句2;    
    }
    ....
    else
    {
        C语句n;    
    }
-------------------shell的格式------
单分支
    if 表达式
    then
        SHELL语句
    fi
执行流程:如果表达式为真,则执行shell语句,否则退出
双分支
    if 表达式
    then
        shell语句1
    else
        shell语句2
    fi
执行流程:如果表达式为真,则执行shell语句1,否则执行shell语句2
多分支
    if 表达式1
    then
        shell语句1
    elif 表达式2
    then
        shell语句2
    ....
    else
        shell语句n
    fi
执行流程:如果表达式1为真,则执行shell语句1,结束
        如果表达式1为假,则继续判断表达式2,如果表达式2为真,则执行shell语句2,结束
        重复以上过程

  1.2 shell选择结构练习

        1.输入一个数,判断奇数偶数

        2.输入一个数,判断是否是水仙花

        水仙花:各个位数字立方和等于本身,是三位数

        eg: 153==1*1*1+5*5*5+3*3*3

        if ((a%2==0))

        then

        偶数

        else

        奇数

        fi

        if ((a%2==0))

        then

        偶数

        fi

        if ((a%2!=0))

        then

        奇数

        fi

        if ((a%2==0))

        then

        偶数

        elif ((a%2!=0))

        then

        奇数

        fi

#!/bin/bash


read -p "please enter a:" a
if ((a%2==0))
then
    echo 偶数
else
    echo 奇数
fi

read -p "please enter  num:" num

if (($num>100&&num<999))
then
    g=$((num%10))
    s=$((num/10%10))
    b=$((num/100))
    if ((g**3+s**3+b**3==num))
    then
        echo 是水仙花
    else                                
        echo 不是水仙换
    fi
else
    echo 不是三位数
fi

  1.3 test指令和if结合

        1.test是一个指令:必须添加空格,必须写$,必要时写双引号 man test

        2.test实现的操作:逻辑运算,关系运算,字符串,文件

        3.test指令等价于[]

    1.3.1 test和if结合的格式

格式1:
    if test 表达式
    then
        shell语句
    fi
格式2:
    if [ 表达式 ]    注意[]的左右必须添加空格
    then
        shell语句
    fi

    1.3.2 test的指令

        【1】逻辑运算

                格式1:if [ 表达式1 -a 表达式2 ]

                格式2:if [ 表达式1 ] && [ 表达式2 ]

                格式3:if [ 表达式1 -o 表达式2 ]

                格式4:if [ 表达式1 ] || [ 表达式2 ]

1.判断表达式为真
  ( EXPRESSION )
        EXPRESSION is true
        
    判断a不为0
     if(a!=0) --->if(a)   --->if [ $a ]
              
2.判断表达式为假
 ! EXPRESSION
        EXPRESSION is false
    判断a等于
    if(a==0) ---->if(!a) ---->if [ ! $a ]
3.逻辑与运算,遇假则假,全真为真    
 EXPRESSION1 -a EXPRESSION2
        both EXPRESSION1 and EXPRESSION2 are true
    判断a>b>c
    if(a>b&&b>c) ---->if [ $a -gt $b -a $b -gt $c ]
                    --->if [ $a -gt $b ] && [ $b -gt $c ]
 4.逻辑或运算,遇真则真,全假为假                                       
 EXPRESSION1 -o EXPRESSION2
        either EXPRESSION1 or EXPRESSION2 is true
    判断成绩不合格<0  >100
    if(a<0 || a>100)  --->if [ $a -lt 0 -o $a -gt 100 ]
                      --->if [ $a -lt 0 ] || [ $a -gt 100 ]  
练习:输入一个年份,判断润年
    润年:能被4整除,但不可以被100整除,或者可以被400整除
   read -p "please enter year:" year

if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]
then
    echo 是润年
else
    echo 不是润年
fi
                                                                        

        判断偶数  ---》if [ a%4==0 ]  --->if [ $((a%4)) -eq 0 ]
        【2】关系运算
1.判断两个整数是否相等
     INTEGER1 -eq INTEGER2
              INTEGER1 is equal to INTEGER2
    判断a和b相等
    if test $a -eq $b   ----> if [ $a -eq $b ]
 2.判断整数1大于等于整数2       
       INTEGER1 -ge INTEGER2
              INTEGER1 is greater than or equal to INTEGER2
    判断a大于等于b
    if test $a -ge $b   ----> if [ $a -ge $b ]
3.判断整数1大于整数2    
       INTEGER1 -gt INTEGER2
              INTEGER1 is greater than INTEGER2
4.判断整数1小于等于整数2
       INTEGER1 -le INTEGER2
              INTEGER1 is less than or equal to INTEGER2
5.判断整数1小于整数2
       INTEGER1 -lt INTEGER2
              INTEGER1 is less than INTEGER2
6.判断两个整数不相等
       INTEGER1 -ne INTEGER2
              INTEGER1 is not equal to INTEGER2

练习:输入三个数,实现升序排序
    a b c  要求:a存储最小值  b存储中间值   c存储最大值
#!/bin/bash

read -p "please enter arr" -a arr

#1.判断arr[0]  arr[1]
if [ ${arr[0]} -gt ${arr[1]} ]
then
    t=${arr[0]}
    arr[0]=${arr[1]}
    arr[1]=$t
fi

#判断arr[1] arr[2]
if [ ${arr[1]} -gt ${arr[2]} ]
then
    t=${arr[1]}
    arr[1]=${arr[2]}
    arr[2]=$t
fi                                      


#判断arr[0] arr[1]
if [ ${arr[0]} -gt ${arr[1]} ]
then
    t=${arr[0]}
    arr[0]=${arr[1]}
    arr[1]=$t
fi
echo ${arr[*]}
        【3】字符串
1.判断字符串长度不为0
    -n STRING
         the length of STRING is nonzero
    
  STRING equivalent to -n STRING
  判断str不为空
  if [ -n "$str" ]
2.判断字符串长度为0
  -z STRING
         the length of STRING is zero
    判断str为空
  if [ -z "$str" ]      
3.判断两个字符串是否相等
  STRING1 = STRING2
         the strings are equal
    判断字符串ab是否相等
    if [ $a = $b ]              
4.判断两个字符串不相等
  STRING1 != STRING2
         the strings are not equal
   判断字符串ab不相等
    if [ $a != $b ]     
5.判断字符串的大小关系
    if [ $a > $b ]    
    if [ $a < $b ]   

  练习:输入两个字符串,如果有一个为空则提示空,否则判断= >  <
read a
read b
if [ -z "$a" -o -z "$b" ]
then
    echo NULL
else
    if [ $a "=" $b ]
    then
        echo  "="
    elif [ $a ">" $b ]            
    then
        echo ">"
    elif [ $a "<" $b ]
    then
        echo "<"
    fi
fi
        【4】文件

                文件类型:bcd-lsp

                参数: bcdfLSp

1.判断两个文件谁跟新(修改的时间)
   FILE1 -nt FILE2
         FILE1 is newer (modification date) than FILE2
     两个文件file1  file2
      if [ $file1 -nt $file2 ]     
 2.判断文件谁跟旧            

  FILE1 -ot FILE2
         FILE1 is older than FILE2
     两个文件file1  file2
      if [ $file1 -ot $file2 ]  
 3. 判断是否是块设备文件以及存在        

  -b FILE
         FILE exists and is block special
    文件file是否是块设备文件
     if [ -b $file ]    
4. 判断文件存在且是一个字符设备文件    

  -c FILE
         FILE exists and is character special
           if [ -c $file ] 
5.判断文件存在且是一个目录               

  -d FILE
         FILE exists and is a directory

 6.判断文件是否存在
   -e FILE
         FILE exists
7.判断文件存在且是一个普通文件
  -f FILE
         FILE exists and is a regular file
8.判断文件存在且是一个链接文件         





  -h FILE
         FILE exists and is a symbolic link (same as -L)


  -L FILE
         FILE exists and is a symbolic link (same as -h)


9.判断文件存在且是一个管道文件
  -p FILE
         FILE exists and is a named pipe
10.判断文件存在且文件大小大于0,文件不为空         



  -s FILE
         FILE exists and has a size greater than zero
11.判断文件存在且是一个套接字文件
  -S FILE
         FILE exists and is a socket



12.判断文件存在且具备可读权限
    -r FILE
         FILE exists and read permission is granted
13.判断文件存在且具备写权限         
  -w FILE
         FILE exists and write permission is granted
14.判断文件存在且具备可执行权限         
  -x FILE
        FILE exists and execute (or search) permission is granted

练习:终端输入文件名,输出文件对应的类型以及对应的权限

  1.4 case ..in

---------------C语言switch----
switch(表达式)
{
    case 常量表达式1:C语句; break;
    case 常量表达式2:C语句; break;
    case 常量表达式3:C语句; break;
    ...
    default:C语句n;break;
}
----------------case..in--------
格式:
case varName in
    常量表达式1)
        shell语句
        ;;        
        常量表达式2)
        shell语句
        ;;            ------》不可以省略
      ....
      *)
         shell语句
         ;;            ----》可以省略不写                                                     
 esac    
 解析:
 1.varName:只是一个变量  类似switch中的表达式     
 2.常量表达式:
      2.1常见格式:
          hello)
          'hello')
          "hello") 
      2.2可以和按位或链接
         A|a)    --->A或a则执行
         Y|y|yes|YES) 
      2.3可以和通配符结合使用
          h*)  
          ?
          []   
          70-89B
          [7-8][0-9])
 3.;; --->类似C语言break,退出case..in,  可有可无  
 4.*) 类似default  执行除上面案例的所有情况 
 
 
练习:输入一个表达式,输出对应的值  +-*%       
   1+2       ---》3   
   a=1
   b=+
   c=2
   switch(b)
   {
       case '+':printf("%d",a+b);break;
        case '-':printf("%d",a+b);break; 
        case '*':printf("%d",a+b);break; 
        case '/':printf("%d",a+b);break;
        case '%':printf("%d",a+b);break;
        default:error;break;
   }
   
read a b c
case $b in
    +)
        echo $a$b$c=$((a+c))
        ;;
    -)
        echo $a$b$c=$((a-c))
        ;;
    "*")
        echo $a$b$c=$((a*c))
        ;;
    /)                       
        echo $a$b$c=$((a/c))
        ;;
    %)
        echo $a$b$c=$((a%c))
        ;;
    *)
        echo input error
        ;;

esac

二、shell循环结构

        1.回顾C语言的循环:while\ for\ do..while

        2.shell的循环: while\for\select..in

  2.1 while

------------------C语言----
while(表达式)
{
    C语句
}
------------------shell循环格式----
格式
    #while test 表达式
    while [ 表达式 ]         --->while [ 1 ]  死循环
    do
        shell语句
    done
执行流程:如果表达式为真则进入循环,表达式为假则退出循环

练习:循环1--5      
      i=1
      while [ $i -le 5 ]
      do
         echo i=$i
          ((i++))
      done
      
练习:输入一个数组,使用while循环输出数组元素,计算数组元素的和
read -p "please enter arr:" -a arr
i=0
while [ $i -lt ${#arr[*]} ] 
do
    echo arr[$i]=${arr[$i]}  
    ((sum+=arr[i]))
    ((i++))
done
echo sum=$sum        

  11.2 for

        while:属于当型循环,先判断后执行,最少执行0次,属于有条件控制(不清楚循环次数)

        for: 属于当型循环,先判断后执行,最少执行0次,属于计数控制(循环次数明确)

        do..while:属于直到型循环,先执行后判断,最少执行1次,属于条件控制(循环次数不明确)

---------------------C语言for循环格式----
for(表达式1;表达式2;表达式3)
{
    C语句
}
表达式1:起始值
表达式2:循环条件
表达式3:步长
-------------------shell的格式--------
格式1:类似于C语言的格式
    for ((表达式1;表达式2;表达式3))
    do
        shell语句
    done
执行流程:先表达式1,执行表达式2,如果表达式2为真则继续循环,后执行表达式3,如果表达式2为假
则结束循环
格式2:可以实现稀疏数组的循环
    for varName in 选项列表
    do
        shell语句
    done
格式3:
     for varName     -----》
    do
        shell语句
    done
    
    注意:"in 选项列表"如果不写,则默认varName的结果是终端输入的字符串也就是命令置换$1 $2 $3...
解析:
1.varName: 循环变量,类似i
2.选项列表:每个元素之间使用空格隔开
    2.1 选项列表为固定的字符换
    for i in 1 2 3 4
    do
        echo $i
    done
    2.2 选项列表的值为数组
    arr=(11 22 33)
    for i in ${arr[*]}
    do
       echo $i
    done
    2.3 选项列表可以使用seq指令
    格式:seq 起始值 间隔 终止值
        eg: seq 1 2 10   ----->1 3 5 7 9
        使用: `seq 起始值 间隔 终止值`      $(seq 起始值 间隔 终止值)   
     for i in `seq 2 2 8`   
     
     a=2 b=8
     for i in `seq $a 2 $b` 
     2.4 选项列表可以使用{1..3},起始值和终止值必须是常量
               {1..3} --->1 2 3           
3.执行流程:依次把选项列表的每个元素赋值给变量varName,如果选项列表的元素赋值结束,则结束循环

练习:输入一个数组,计算最大值,使用for实现
练习: 打印图片
    *
    **
    ***
    ****

for((i=1;i<=4;i++))
do
    for((j=1;j<=i;j++))
    do
        echo -n "*" #取消换行打印
    done
    echo   #换行
done
                                        

read -p "please enter arr:" -a arr
max=${arr[0]}
for var in ${arr[*]}
do
    if [ $max -lt $var ]
    then

        max=$var
    fi
done
echo max=$max

  2.3 select..in

        select..in: 增强和终端页面的交互性

格式:
    select varName in 选项列表
    do
        shell语句
    done
解析:
1.varName和选项列表:  与for循环一样
2.select..in执行流程:在#?的后面输入指定序列,如果序列号存在,则把指定对应的元素赋值给varName
    如果#?不输入世界回车,则重新打印页面,如果在#?的后面输入的值不在列表中,则重新输入
    ctrl c\  ctrl d结束循环
eg:
select var in 11 22 33 44
do
    echo var=$var
done                      

  2.4 select..in和case..in结合使用

练习:使用select..in和case..in实现计算器
    1)+
    2)-
    3)*
    4)/
    5)%
    #?
read a  c   #1  2
select b in + - "*" / %
do
    case $b in                       
        +)
            echo $a$b$c=$((a+c))
            ;;
        -)
            echo $a$b$c=$((a-c))
            ;;
        "*")
            echo $a$b$c=$((a*c))
            ;;
        /)                       
            echo $a$b$c=$((a/c))
            ;;
        %)
            echo $a$b$c=$((a%c))
            ;;
        *)
            echo input error
            ;;

        esac
    done

三、练习:

  3.1 使用case..in实现等级判断,输入一个成绩,判断等级

#!/bin/bash

read grade
case $grade in
	9[0-9]|100)
		echo A
		;;
	8[0-9])
		echo B
		;;
	7[0-9])
		echo C
		;;
	6[0-9])
		echo D
		;;
	[1-5][0-9]|[0-9])
		echo 不及格
		;;
	*)
		echo error
		;;
esac

  3.2任意输入一个数,使用while循环计算各个位数字之和

#!/bin/bash

read -p "请输入一个数:" num
sum=0
n=$num
while [ $num -gt 0 ]
do
	sum=$((num%10+$sum))
	num=$((num/10))
done
echo $n各个位数和为$sum

  3.3 输入一个字符串,使用while循环实现字符串逆置

#!/bin/bash

read str
len=${#str}
echo str=$str
for i in `seq 1 1 $len`
do
	NewStr=$NewStr${str:0-i:1}
done
echo 逆置后:str=$NewStr

  3.4循环家目录下的所有内容,计算家目录下 目录的个数,普通文件的个数,使用for循环

#!/bin/bash

arr=(`ls ~`)
len=${#arr[*]}
qt=0
for i in `seq 0 1 $(($len-1))`
do
	if [ -d ~/${arr[$i]} ]
	then
		((qt++))
	fi
done
echo 家目录下目录数量为$qt
qt=0
for i in `seq 0 1 $(($len-1))`
do
	if [ -f ~/${arr[$i]} ]
	then
		((qt++))
	fi
done
echo 家目录下普通文件数量为$qt

  3.5 打印图形

        *

        ***

        *****

        *******

#!/bin/bash

for i in {1..4}
do
	for ((j=4-i;j>0;j--))
	do
		echo -n " "
	done
	for ((k=2*i-1;k>0;k--))
	do
		echo -n "*"
	done
	echo 
done

  3.6 输入一个数组,请实现冒泡排序

#!/bin/bash

read -p "请输入数组元素:" -a arr
len=${#arr[*]}
for i in `seq 1 1 $len`
do
	for j in `seq 0 1 $(($len-$i-1))`
	do
		if [ ${arr[$j]} -gt ${arr[$((j+1))]} ]
		then
			temp=${arr[$j]}
			arr[j]=${arr[$((j+1))]}
			arr[$((j+1))]=$temp
		fi
	done
done

echo ${arr[*]}

  3.7 输入一个数组,请实现插入排序

#!/bin/bash

read -a arr -p "请输入数组中的元素:"
len=${#arr[*]}
sun=0
for i in `seq 1 1 $(($len-1))`
do
	temp=${arr[$i]}
	for ((j=i-1;j>=0;j--))
	do
		if [ $temp -le ${arr[$j]} ]
		then
			arr[$((j+1))]=${arr[$j]}
		else
			arr[$((j+1))]=$temp
			j=-1
		fi
	done
done
echo ${arr[*]}

  3.8 输入用户名和密码(加密输入),实现密码的三次登录 默认用户名admin 密码1234 账户存款10000

如果登录失败,则提示

第1次登录失败,还有2次机会

第2次登录失败,还有1次机会

第3次登录失败,账户被锁定

如果登录成功,则显示银行页面

1.账户余额

2.取款

3.存款

如果选择1,则打印当前的余额

如果选择2,则输入取款金额,如果取款金额大于实际金额,则提示账户余额不足,请重新输入,如果账户余额小于等于实际金额,则提示取款成功,打印剩余金额

如果选择3,则输入存款金额,并提示 存款成功,余额的值

#!/bin/bash

count=1
balance=10000
while [ $count -le 3 ]
do
	read -p "请输入用户名:" name
	read -p "请输入密码:" -s passwd
	if [ $name=="admin" -a $passwd=="1234" ]
	then
		echo
		select choice in 账户余额 取款 存款
		do
			case $choice in
				账户余额)
					echo 账户余额:$balance
					;;
				取款)
					read -p "请输入取款金额:" mount
					if [ $mount -gt $balance ]
					then
						echo 余额不足,请重新输入
					else
						balance=$((balance-mount))
						echo 取款成功
						echo 账户余额:$balance
					fi
					;;
				存款)
					read -p "请输入存款金额:" mount
					balance=$((balance+mount))
					echo 存款成功
					echo 账户余额:$balance
					;;
				*)
					echo error
					;;
			esac
		done
	elif [ $name!="admin" || $passwd!="1234" ]
	then
		if [ $count -eq 3 ]
		then
			echo 第$count次登录失败,账户被锁定
		else
			echo "第$count次登录失败,还有$((3-$count))次机会"
		fi
		((count++))
	fi
done

相关文章:

  • Professional Pycharm教程
  • Jmeter基础知识总结
  • [笔记.AI]AI知识科普提纲
  • 《昇思25天学习打卡营第14天|计算机视觉-ShuffleNet图像分类》
  • Flutter 学习之旅 之 flutter 在 Android 端读取相册图片显示
  • 浅谈对目前 Deep Seek 的看法
  • HOW POWERFUL ARE GRAPH NEURAL NETWORKS?(GIN)
  • DAV_postgresql_2-user_role
  • unity 红点树
  • 网络安全应急响应中主机历史命令被删除 网络安全事件应急响应
  • JAVA面试常见题_基础部分_mybatis面试题
  • Spark RDD持久化机制深度解析
  • sql server 复制从备份初始化数据
  • Ubuntu中dpkg命令和apt命令的关系与区别
  • 大模型算法工程师的技术图谱和学习路径
  • AI 自动化编程:从效率革命到未来教育的革新
  • 请求Geoserver的WTMS服务返回200不返回图片问题-跨域导致
  • 【leetcode hot 100 42】接雨水
  • unity学习57: toggle/选项/切换, 实现单选和多选效果
  • ptaC语言4-3 求给定精度的简单交错序列部分和
  • 贵州省总工会党组成员、副主席梁伟接受审查调查
  • 美众议院通过法案将“墨西哥湾”更名为“美国湾”
  • 105岁八路军老战士、抗美援朝老战士谭克煜逝世
  • 中国中古史集刊高质量发展论坛暨《唐史论丛》创刊四十周年纪念会召开
  • 暴雨及强对流天气黄色预警已发布!南方进入本轮降雨最强时段
  • 绿城约13.93亿元竞得西安浐灞国际港港务片区地块,区内土地楼面单价首次冲破万元