【shell 编程大全】数组,逻辑判断以及循环

数组,逻辑判断以及循环

1. 概述

大家好,我又来了。今天呢我们继续学习shell相关的知识。还是老样子我们先回顾下上一次【脚本交互 以及表达式】学习到的知识

  • 登录shell 关联配置文件
  • 什么是子shell
  • umask 修改默认权限
  • read 基础
  • 表达式
    • 简单计算表达式
    • expr 计算
    • bc 计算
    • 测试 表达式
    • 逻辑表达式
    • 字符串表达式
    • 文件表达式
    • 数字表达式
    • 测试进阶表达式
    • 逻辑组合表达式

我们简单回顾了下上次学习的内容。废话不多说了,接下来让我们一起学习新的内容

2. 数组

2.1 格式定义

格式

# 在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的语法格式:
array_name=(value1 ... valuen)

格式解读

单行定义
array_name=(value0 value1 value2 value3)

多行定义
array_name=(
    value0
    value1
    value2
    value3
)

单元素定义
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

2.2 具体案例

单行定义案例

[vagrant@localhost test003]$ echo ${array1}

[vagrant@localhost test003]$ array1=(11 22 33 44 55)
[vagrant@localhost test003]$ echo ${array1}
11
[vagrant@localhost test003]$ echo ${array1[@]}
11 22 33 44 55
[vagrant@localhost test003]$ 

多行定义案例

[vagrant@localhost test003]$ echo ${array2[@]}

[vagrant@localhost test003]$ array2=()
[vagrant@localhost test003]$ array2=(
> aa
> bb
> cc
> dd
> )
[vagrant@localhost test003]$ echo ${array2[@]}
aa bb cc dd
[vagrant@localhost test003]$ 

单元素定义案例

[vagrant@localhost test003]$ echo ${array3[@]}

[vagrant@localhost test003]$ array3[0]=bb
[vagrant@localhost test003]$ array3[1]=ff
[vagrant@localhost test003]$ array3[2]=ee
[vagrant@localhost test003]$ echo ${array3[@]}
bb ff ee
[vagrant@localhost test003]$ 

命令行定义案例

[vagrant@localhost test003]$ echo ${array4[@]}

[vagrant@localhost test003]$ array4=$(ls ../)
[vagrant@localhost test003]$ echo ${array4[@]}
test001 test002 test003
[vagrant@localhost test003]$ 

2.3 多种取值方式

格式

基于索引找内容
	读取数组元素值可以根据元素的下标值来获取,语法格式如下:
    	${array_name[index]}
    	${array_name[@]:起始位置:获取数量}
注意:
	获取具体的元素内容,指定其下标值,从0开始
	获取所有的元素内容,下标位置写"@"或者"*"

实例

[vagrant@localhost test003]$ num_list=(123 234 345 456 567)
[vagrant@localhost test003]$ echo ${num_list[@]}
123 234 345 456 567
[vagrant@localhost test003]$ echo ${num_list[@]:1:3}
234 345 456
[vagrant@localhost test003]$ 

2.4 获取数组长度

格式

在变量前面添加符号#

${#num_list[0]}

实例

[vagrant@localhost test003]$ echo ${num_list[@]}
123 234 345 456 567
[vagrant@localhost test003]$ echo ${#num_list[@]}
5
[vagrant@localhost test003]$ 

2.5 获取系统所数组

格式

declare -a

具体实例

[vagrant@localhost test003]$ declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -ar BASH_REMATCH='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a array1='([0]="11" [1]="22" [2]="33" [3]="44" [4]="55")'
declare -a array2='([0]="aa" [1]="bb" [2]="cc" [3]="dd")'
declare -a array3='([0]="bb" [1]="ff" [2]="ee")'
declare -a num_list='([0]="123" [1]="234" [2]="345" [3]="456" [4]="567")'
[vagrant@localhost test003]$ 

2.6 数组替换/ 数组删除

格式

元素内容替换:
	array_name[index]=值
注意:
	在修改元素的时候,index的值一定要保持准确

元素部分内容替换,可以参考字符串替换格式:
	${array_name[index]/原内容/新内容}
注意:
	默认是演示效果,原数组未被修改,如果真要更改需要结合单元素内容替换

删除单元素
	unset array_name[index]
删除整个数组
	unset array_name

具体案例

[vagrant@localhost test003]$ unset array6
[vagrant@localhost test003]$ array6=(11 22 aa bb cc ddd ggg)
[vagrant@localhost test003]$ echo ${array6}
11
[vagrant@localhost test003]$ echo ${array6[@]}
11 22 aa bb cc ddd ggg
[vagrant@localhost test003]$ array6[0]=99
[vagrant@localhost test003]$ echo ${array6[@]}
99 22 aa bb cc ddd ggg
[vagrant@localhost test003]$ array6[5]=${array6[5]/ddd/ert}
[vagrant@localhost test003]$ echo ${array6[@]}
99 22 aa bb cc ert ggg
[vagrant@localhost test003]$ unset array6[5]
[vagrant@localhost test003]$ echo ${array6[@]}
99 22 aa bb cc ggg
[vagrant@localhost test003]$ unset array6
[vagrant@localhost test003]$ echo ${array6[@]}

[vagrant@localhost test003]$ 

3. 逻辑判断

3.1 if 判断

3.1.1 格式

单分支格式

单路决策 - 单分支if语句
	样式:
        if [ 条件 ]
        then
            指令
        fi
    特点:
    	单一条件,只有一个输出

双分支格式

双路决策 - 双分支if语句
	样式:
        if [ 条件 ]
        then
            指令1
        else
            指令2
        fi
    特点:
    	单一条件,两个输出

多分支格式

多路决策 - 多分支if语句
	样式:
		if [ 条件 ]
        then
            指令1
        elif [ 条件2 ]
        then
            指令2
        else
            指令3
        fi
	特点:
    	n个条件,n+1个输出

单行格式

单行命令写法
	if [ 条件1 ]; then 指令1; elif [ 条件2 ]; then 指令2; ... ; else 指令n; fi
3.1.2 实例

单行实例

#!/bin/bash

# 单个if 判断
gender="$1"

if [ "${gender}" == "男" ]
then
  echo "你是男的"
  exit
fi

echo "你不是男的"

双分支实例

#!/bin/bash

# 双分支实例

gender="$1"

if [ "${gender}" == "nan" ]
then
  echo "你是男的"
else
  echo "你是女的"
fi

多分支实例

#!/bin/bash

# 多分支实例

gender="$1"

if [ "${gender}" == "nan" ]
then
  echo "你是男的"
elif [ "${gender}" == "nv" ]
then
  echo "你是女的"
else
  echo "我不知道你的性别"
fi
3.1.3 经典实例
3.1.3.1 奇偶数 判断
#!/bin/bash

# 计算判断


# 引导客户输入一个数字
read -p "请输入一个数字" num

# 判断是基数 还是 偶数
if (( ${num} % 2 == 0 ))
then
  echo "你是偶数"
else
  echo "你是奇数"
fi
3.1.3.2 正则 判断
#!/bin/bash

# 表示正则判断

read -p "您输入一个字符串: " string

if [[ ${string} == v*  ]]
then
  echo "你是满足以v开头的"
else
  echo "你不满足以v开头"
fi

3.2 case 判断

格式

case 变量名 in
   值1)
      指令1
         ;;
   ...
   值n)
 	   指令n
         ;;
esac

实例

#!/bin/bash

# 进行case 练习判断

type="$1"

case ${type} in
  "1")
        echo "你是1"
	;;
  "2")
        echo "你是2"
	;;
  *)
 	echo "你是几我也不知道"
	;;
esac

3.3 for 循环

格式

循环逻辑语法解析:
	关键字 [ 条件 ]
	do
		执行语句
	done
	
注意:
	这里的关键字主要有四种:
		for 	- 循环遍历一个元素列表
		while	- 满足条件情况下一直循环下去
		until	- 不满足条件情况下一直循环下去
		select	- 一种特殊的循环遍历,侧重于遍历用户输入,一般结合case等语句使用

实例1:遍历命令列表

#!/bin/bash

# 进行for循环


for i in $(ls /)
do
  echo "您的路径是${i}"
done

实例2:遍历参数列表

查看脚本内容
[root@localhost ~]# cat for_arg_list.sh
#!/bin/bash
# 功能:脚本参数列表 for循环
for i in $@
do
  echo "列表元素: ${i}"
done

脚本执行后效果
[root@localhost ~]# /bin/bash for_arg_list.sh 1 2 3
列表元素: 1
列表元素: 2
列表元素: 3
3.3.1 多种案例

案例1

#!/bin/bash


# 进行循环案例

for i in yuwen shuxue lishi
do
  echo "列表元素: ${i}"
done

案例2

#!/bin/bash

# 循环

for i in {1..3}
do
  echo "元素内容是: ${i}"
done

案例3

#!/bin/bash

# 实现脚本参数遍历

for i in $@
do
  echo "元素内容是: ${i}"
done
3.3.2 综合实践

随机生成用户

#!/bin/bash

# 随机创建用户

user_file="/tmp/user.txt"


# 检查是否是文件
[ -f ${user_file} ] && > ${user_file}


# 开始批量创建用户
for i in {1..5}
do

  # 创建密码
  pwd="aaa$RANDOM"
  # 创建用户
  sudo useradd user-${i}

  # 设置密码
  echo ${pwd} | passwd --stdin user-${i} > /dev/null 2>&1
  
  # 开始输出信息
  echo "创建账号是: user-${i}, 该用户的密码是: ${pwd}"
  echo -e "创建的账号是: \033[31;41muser-${i}\033[0m 该用户的密码是: \033[31;41m${pwd}\033[0m"

done
#!/bin/bash

# 进行批量的用户删除

for i in {1..5}
do
  sudo userdel -r user-${i}
  echo "用户【user-${i}】删除成功"
done

对特定的网段的主机进行扫描

#!/bin/bash

# 对特定ip进行扫描

base_net=192.168.56
net_file='/tmp/host.txt'

# 判断文件是否存在
if [ -f ${net_file} ]
then
  sudo echo '' > ${net_file}
fi


for i in {1..100}
do
  # 开始检测主机
  host_status=$(ping -c1 -W1 ${base_net}.${i} > /dev/null 2>&1 && echo "UP" || echo "DOWN")
  sudo echo "${base_net}.${i} 主机状态: ${host_status}" >> ${net_file}
  sudo echo "${base_net}.${i} 主机状态: ${host_status}" 
done


# 输出信息
live_num=$(grep UP ${net_file} | wc)
unlive_num=$(grep DOWN ${net_file} | wc)

echo -e "\e[31m${netsub}.0 网段主机存活情况\e[0m"
echo "------------------------------------"
echo -e "\e[32m${netsub}.0 网段存活主机数量: ${live_num}\e[0m"
echo -e "\e[32m${netsub}.0 网段异常主机数量: ${unlive_num}\e[0m"
3.3.3 循环赋值
#!/bin/bash

# 进行循环赋值

all_sum=0
odd_sum=0
even_sum=0


for i in {1..100}
do
  let all_sum+=i
done


for i in {1..100..2}
do
  let odd_sum+=i
done

for i in {0..100..2}
do
  let even_sum+=i
done

echo -e "所有的数字之和是: \033[31m${all_sum}\033[0m"
echo -e "所有的数字之和是: \033[31m${odd_sum}\033[0m"
echo -e "所有的数字之和是: \033[31m${even_sum}\033[0m"
3.3.4 (()) 版的双括号的语法
#!/bin/bash

# 使用特殊符号(()) 来进行计算

all_sum=0


for ((i=0; i<=100; i+=1))
do
  let all_sum+=i
done

echo -e "计算结果是: \033[31m${all_sum}\033[0m"
3.3.4.1 综合实践:命令行进度条数字
#!/bin/bash


# 实现数字进度条

for ((i=0; i<=100; i+=1))
do
  // 防止信息输出的叠加,采用\e[4D,每次输出信息的时候,光标左移4个位置,信息不会出现叠加
  printf "\e[4D%3d%%" $i
  sleep 0.1
done
3.3.4.2 综合实践:实现进度条
#!/bin/bash

# 实现数字进度条

str="#"
arr=("|" "/" "-" "\\")

for ((i=0; i<=50; i+=1))
do
  let index=i%4
  printf "[%-50s][%d%%]%c\r" "$str" "$(($i*2))" "${arr[$index]}"
  sleep 0.2
  str+="#"
done

echo ""
3.3.4.3 综合实践:保存数字最大值 以及最小值
#!/bin/bash
# 设定随机数比大小

# 设定基本变量
declare -i min max
declare -a nums

# 设定大小比较
for ((i=0;i<10;i++))
do
    # 将随机数添加到数组中
    nums[$i]=$RANDOM
    # 设定初始值
    [ $i -eq 0 ] && min=${nums[0]} max=${nums[0]}
    # 设定最大值
    [ ${nums[$i]} > $max ] && max=${nums[$i]}
    # 设定最小值
    [ ${nums[$i]} < $min ] && min=${nums[$i]}
done
echo -e "\e[31m    随机数的统计信息\e[0m"
echo "------------------------------"
echo -e "\e[32m所有的随机数:${nums[@]}"
echo -e "最大的随机数:${max}"
echo -e "最小的随机数:${min}\e[0m"

3.4 while 循环

基础语法

场景:只要条件满足,就一直循环下去
    while [ 条件判断 ]
    do
       执行语句
    done

具体实例

#!/bin/bash

# 通过while 循环来执行


all_num=0
odd_num=0
even_num=0

i=0
while (( i <= 100 ))
do
  let all_num+=i
  let i++
done


i=0
while ((i<=100))
do
  ((odd_num+=i))
  ((i+=2))
done

i=1
while ((i<=100))
do
  ((even_num+=i))
  ((i+=2))
done

echo "累加的和是:${all_num}"
echo "奇数累加的和是: ${odd_num}"
echo "偶数累加的和是: ${even_num}"
3.4.1 while read 用法

格式

while中有一种特殊的语法,while read line 它可以从文本中逐行读取相关的内容,然后存储到一个临时变量line中,然后我们后续就可以逐行对文本内容进行操作

样式1: cat提前读				
cat a.log | while read line
do                         
    echo "File: ${line}"     
done 

实例1

#!/bin/bash

# 通过while read 逐行读取

i=0

env | while read line
do
  ((i+=1))
  echo "第${i}行内容是: ${line}"
done

实例2

exec 0< a.log    
while read line  
do               
    echo "${line}"
done

实例3

while read line
do
    echo "File: ${line}"
done < a.log

3.5 until循环

使用方式跟while保持一致。

格式

场景:只要条件不满足,就一直循环下去
    until [ 条件判断 ]
    do
       执行语句
    done

3.6 select 条件选择

语法格式

select 变量名 in  input_list 
do 
    循环语句 
done
语法解读:
	1 select 从 input_list 获取相关的值,然后输出到一个菜单列表,元素格式如下:
		序号) 菜单条目
	2 用户输入信息的标识使用PS3 的值,默认值是#?。
		我们可以定制PS3环境变量
	3 如果用户输入菜单序号,则输出菜单内容
	4 select的退出方式有很多种
		强制退出:Ctrl+D 组合键
		普通退出:结合break方式

实例1

#!/bin/bash

# 通过select 进行简单选择

echo "您喜欢的系统是:"
select osname in "HarmonyOS" "Linux" "Windows" "Ubuntu"
do
  echo "您选择的系统是: ${osname}"
  exit
done

实例2

#!/bin/bash

# 修改输入指令

PS3='请选择菜单序号: '

echo "请输入您喜欢的系统: "
select osname in "os" "linux" "window"
do
  echo "您选择的操作系统是: ${osname}"
  exit
done
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值