一、for循环

for循环语法

语法格式一:
    for 变量 in 取值列表
      do
        命令列表
      done
语法格式二:
    for ((初始值;循环变化条件;变量变化))    # 类C风格
       do
         命令列表
       done
   
 # for (( ; ; ))无限循环

for循环常用格式

#!/bin/bash

1、第一种格式
     for i in 1 2 3 4 5 6 7
        do
          echo $i
         done

2)第二种格式  #类C风格
       for ((i=1;i<=7;i++))
          do
             echo $i
          done

3)第三种格式
       for i in `cat /shells/test`                                         
           do
             echo $i
            done
 
4)第四种格式
       for i in {1..100..2}	
       do
       		echo $i
       done
 
5)第五种格式
        for i in `seq 1 7`
        do
        	echo $i
        done

for循环 实例一:检测192.168.10.0网段IP是否联通

#shell脚本并发控制测试
{程序}&表示将程序放到后台执行,如果需要等待程序执行完在进行下面的内容,就在done的后面加wait

#!/bin/bash
ip=192.168.10
# read -p "请输入你要测试的网段:" ip

for ((i=1;i<=254;i++))
  do
{
    ping -c1 -i 0.2 $ip.$i &>/dev/null
  if [ $? -eq 0 ];then
      echo "$ip.$i is up" >>/tmp/ip_up.txt
  else
      echo "$ip.$i is down" >>/tmp/ip_down.txt
  fi
 }&

  done
wait	# 等待前面的语句执行完,再执行下面的语句
  echo "ip 地址查询完毕!"

二、while循环

while循环语法

语法格式一:
    while [条件]	# 条件放 “ture”或“:”即为无限循环
    do
        操作
    done

语法格式二:
    while read line
    do
        操作
    done  <  file.txt

通过read命令每次读取一行文件,文件内容有多少行,while循环多少次

while循环 实例一:猜数字

#!/bin/bash
price=50
times=0

echo "请在0-99之间随机猜取一个数字: " 
while true
do
	read -p "input a price: " int
	let times++
	if [ $int -eq $price ];then
		echo "恭喜,猜对了"
		echo "你一共猜了 $times 次"
		exit 105	# 自定义退出状态码 105
		
	elif [ $int -gt $price ];then
		echo "猜大了"
	else
		echo "猜小了"
	fi
done

for、while、if 循环嵌套 实例二:添加用户 脚本

#!/bin/bash
#add user
while :
do
	read -p "please enter prefix & password & num: " prefix pass num  # 位置参数
	read -p "用户名 & 密码 & 创建的数量: " prefix pass num  # 位置参数
	printf "user information: 
	-------------------------
	user prefix: $prefix
	user passwd: $pass
	user number: $num
	-------------------------
	# test1 created
	# test2 created
"

for i in `seq -w $num`
do
	user=${prefix}${i}
	id user &> /dev/null
	if [ $? -ne 0 ];then
		useradd $user
		echo "$pass" | passwd --stdin $user &> /dev/null
		if [ $? -eq 0 ];then
			echo -e "\033[31m$user\033[0m created"
		fi	
	else
		echo "user $user exist"
	fi
done
  exit 100
done

实例三:打印9x9乘法表

脚本打印99乘法表
  for i in {1..9};do
     for j in `seq $i`;do
	    echo -en "${j}x$i=$((j*i))\t"
        done
    echo		
  done

实例四:打印指定图案

5
54
543
5432
54321

方法1:
#!/bin/bash
y=5
while (( $y >= 1 ));do
    for ((x=5;x>=$y;x--));do
            echo -n $x
	done
			echo
		let y--
	done

方法2:
#!/bin/bash
for (( y=5;y>=1;y--))
do
        for (( x=5;x>=$y;x--))
        do
        echo -n $x
        done
echo
done

# 直角三角形
*
**
***
****
*****

#!/bin/bash
for ((i=1;i<=5;i++));do
	for((j=1;j<=i;j++));do
    	echo -e "*\c"
	done
   		echo
done

# 等腰三角形
         *
        ***
       *****
      *******
     *********
     
#!/bin/bash
for ((i=1;i<=10;i++));do
	for ((k=1;k<=10-i;k++));do
		echo -e " \c"
	done
        for((j=1;j<=2*i-1;j++));do
            echo -e "*\c"
        done
            echo
	done

三、until循环

  • 和while刚好相反,只要不满足条件就一直循环

until循环语法

until expression  【条件=fslse,死循环】
do 
    command 
done

until循环 实例一:1+..+100的值

#!/bin/bash
# 定义变量的初始值
 i=1
 sum=0

# until循环
until (($i > 100))
  do
   let sum=$sum+$i
   let i++
  done
echo "1-100之间的和:$sum"

四、RANDOM随机数

  • 系统变量:RANDOM,默认会产生0-32767的随机数

调用语法

50-100之间的随机数
echo $[$RANDOM%51+50]	# 最小50,最大100

产生三位之间的随机整数
echo $[$RANDOM%900+100]	# 最小100,最大999

五、exit语句

exit [返回值]	# 取值范围 0-255

含义:
	1、退出时的状态码
	2、在有多个判断语句的情况下,可以通过自定义状态码判断是哪个环节出现了问题,从而可以快速地做出解决方案。
	3、取值范围 0-255

exit 实例一:判断输入是否是yes/no

#!/bin/bash
read -p "请输入(yes|no):" al
case $al in
"yes")
        echo    "您输入的是yes"
        exit 1                                #当选择的是yes后,程序就退出了,不在打印“您的选择是yes”这句话。
        echo    "您的选择是yes"
        ;;
"no")
        echo    "您输入的是no"
        echo    "您的选择是no哦"
        ;;
*)
        echo    "输入错误,请输入yes|no"
esac

六、break语句

Shell break 的语法

break n

含义:跳出当前整次循环

	1、n 表示跳出循环的层数,如果省略 n,则表示跳出当前的整个循环。
	2、break 关键字通常和 if 语句一起使用,即满足条件时便跳出循环。

实例一:使用 break 跳出双层循环

#!/bin/bash
for((i=1; i<=10; i++)); do
    for((j=1; j<=10; j++)); do
        if ((i*j==12)); then
            break
        fi
        printf "%d*%d=%-4d" $i $j $((i*j))   #%s %c %d %f都是格式替代符,-表示将左对齐,不加-表示右对齐
    done
    printf "\n"
done

实例二:批量创建用户

#!/bin/bash
#add user
while :
do
        read -p "please enter prefix & password & num: " prefix pass num
        printf "user information: 
        -------------------------
        user prefix: $prefix
        user passwd: $pass
        user number: $num
        -------------------------
"
read -p "Are you sure? [y/n] " action     
        if [ "$action" = "y" ];then
                break
        fi
done

for i in `seq -w $num`
do
        user=${prefix}${i}
        id $user &> /dev/null
        if [ $? -ne 0 ];then
           useradd $user && echo "$pass" | passwd --stdin $user &> /dev/null
                if [ $? -eq 0 ];then
                        echo -e "\033[31m$user\033[0m created"
                fi
        else
                echo "user $user exist"
        fi
done

实例三:猜数字,系统随机生成随机数

猜数字小游戏,当输入的值和系统随机生成的值是一样的时候则退出,如果大于系统生成的值提示大了,反之就是小了。
  
#!/bin/bash

# 生成一个1到100之间的随机数
secret_number=$((RANDOM % 100 + 1))

# 初始化游戏状态和猜测次数
game_over=false
guesses=0

echo "欢迎来到猜数游戏!"

while [ "$game_over" = false ]; do
    read -p "请猜一个1到100之间的数字:" guess
    ((guesses++))  # 猜测次数加1

    # 检查猜测与随机数的比较
    if ((guess == secret_number)); then
        echo "恭喜你,猜对了!你用了 $guesses 次猜测。"
        game_over=true
        break
    elif ((guess < secret_number)); then
        echo "太小了,请再猜一次。"
    else
        echo "太大了,请再猜一次。"
    fi
done

七、continue 语句

continue的语法

continue n

含义:跳出当次循环
	n 表示循环的层数:

	1、省略 n,只对当前层次的循环语句有效,遇到 continue 会跳过本次循环,忽略本次循环的剩余代码,直接进入下一次循环。
	
	2、带上 n,比如 n 的值为 2,那么 continue 对内层和外层循环语句都有效,不但内层会跳过本次循环,外层也会跳过本次循环。效果相当于内层循环和外层循环同时执行了不带 n 的 continue

实例一:跳出多次循环

## 在continue 不接n,表示仅跳出当次循环,后续循环继续执行

#!/bin/bash
for((i=1; i<=10; i++)); do
    for((j=1; j<=10; j++)); do
        if ((i*j==12)); then
            continue 
        fi
        printf "%d*%d=%-4d" $i $j $((i*j))
    done
    printf "\n"
done     

## 在continue后加一个 2 ,表示退出层数为 2,即跳出内层和外层循环。

#!/bin/bash
for((i=1; i<=10; i++)); do
    for((j=1; j<=10; j++)); do
        if ((i*j==12)); then
            continue 2
        fi
        printf "%d*%d=%-4d" $i $j $((i*j))
    done
    printf "\n"
done

八、shift:位移

  • shift命令用于在未知传入参数个数的情况下,依次遍历每个参数进行取值

shift 语法

shift [num]

实例一:打印参数个数

#!/bin/bash
while [ "$1" ];do
echo "第一个参数为:$1,参数个数为:$#"
  shift
  done
  
[root@localhost ~]# bash shift.sh a b c d
第一个参数为:a,参数个数为:4
第一个参数为:b,参数个数为:3
第一个参数为:c,参数个数为:2
第一个参数为:d,参数个数为:1

$0 是命令本身,所以第一个参数从$1算起,所以 a 是第一个参数$1,b是第二个参数$2,以此类推,所以`shift`(shift 1)命令执行原理是 每执行一次,变量的个数($#)就 减1 (之前的$1变量被销毁,之后的$2就变成了$1),而变量值提前一位

实例二:创建用户

#!/bin/bash
while [ $1 ];do
    if id $1 &>/dev/null;then
        echo $1 is exist!
    else
        useradd $1
    fi
      shift
   done
    echo "All user is created"
    
[root@localhost ~]# bash shift_adduser.sh user1 user2 user3

实例三:计算器

#!/bin/bash
sum=0
while [ $# -ne 0 ]    #判断参数的个数是否为0,如果不为0则开始计算
 do
   let sum=$sum+$1
  shift
 done
 echo $sum

九、shell函数

shell函数语法

function name() {
    statements
    [return value]
}

# 简写
name() {
    statements
    [return value]
}

- `function`是 Shell 中的关键字,专门用来定义函数;
- `name`是函数名;
- `statements`是函数要执行的代码,也就是一组语句;
- `return value`表示函数的返回值,其中 return 是 Shell 关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。

*******************************************
# 函数调用
name
# 如果传递参数,那么多个参数之间以空格分隔:
name param1 param2 param3

# 不管是哪种形式,函数名字后面都不需要带括号。
*******************************************

实例一

[root@localhost ~]# cat fun2.sh 
#!/bin/bash

# 定义函数
function hello(){
   echo hello   
   }

function name() {
    echo name $1 
   }
   
[root@localhost ~]# source fun2.sh	#使脚本生效
[root@localhost ~]# name zhangsan	#传递参数
name zhangsan
[root@localhost ~]# name			#无传参
name
[root@localhost ~]# hello			#调用函数
hello
  • 注意:仅当前进程生效,其他进程和子进程无效。

实例二:定义到用户的环境变量

[user01@localhost ~]$ cat .bashrc 
function hello(){
   echo hello   
   }

function name() {
    echo name $1 
   }
   
[user01@localhost ~]$ source .bashrc 
[user01@localhost ~]$ hello
hello

[user02@localhost ~]$ hello   #用户局部变量,因此user02无法调用
-bash: hello: 未找到命令

实例三:定义到全局用户变量

[root@localhost shell]# vim /etc/bashrc 

function hello() {
   echo hello   
   }
						# 定义函数
function name() {
    echo name $1 
   }
   
[root@localhost shell]# source /etc/bashrc 
[root@localhost shell]# hello
hello
# 切换用户
[root@localhost shell]# su - user02     #由于是全局生效,因此user02用户也可以使用
[user02@localhost ~]$ hello				# 调用函数
hello
  • 可以在一个脚本中定义多个函数

shell函数返回值 - return - 函数的执行状态

实例一:定义return返回的状态码

#!/bin/bash

function test() {
  echo "arg=$1"
  if [ $1 == 1 ]; then
    return 111
  else
    return 100
  fi
}

test 1
echo "该函数的执行状态值为$?"

实例二:结束代码执行–中断输出

[root@localhost ~]# cat fun2.sh 
#!/bin/bash
function hello(){
   echo hello   	# 输出hello
   return   		# 中断输出,不会输出后边的world
   echo world
   }
   
function name() {
    echo name $1 
    }
[root@localhost ~]# source fun2.sh 
[root@localhost ~]# hello     #调用函数
hello
  • 函数返回值在调用该函数后通过 echo $? 来获得。
  • 函数必须要先定义才能被调用

函数参数

$0 取脚本的文件名及路径(命令本身)
$1,$2 给脚本传参数
$* 所有参数看做一个整体
$@ 与$*类似,区别是每个参数是个体
$# 参数个数
$$ 脚本的pid
$? 上一个脚本执行的返回值

实例一:打印位置参数的值

#!/bin/bash

function parm(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
parm 1 2 3 4 5 6 7 8 9 34 73

[root@localhost ~]# ./function4.sh 
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

## $10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

实例二:数组传参

#!/bin/bash
arr=(1 2 3 4 5)
get_sum() {
  sum=0
  for i in $*;do
    let sum+=i
  done
  echo $sum
}

echo "get the array sum is `get_sum ${arr[@]}`"

[root@localhost ~]# ./func5.sh 
get the array sum is 15

实例三:if传参:判断网址是否正常运行

#!/bin/bash
 function chuancan() {           #定义一个chuancan函数提醒用户输入一个网址
   echo "$0 请输入一个网址"     #取脚本的文件名及路径及请输入一个网址!
  exit 1
 }

 function jc_url() {   #定义一个jc_url的函数检测用户输入参数是否正确及检测结果
  wget $1 &>/dev/null #若用户输入传参数是正确的,就执行wget命令
 if [ "$?" -eq 0 ]     #判断以上命令执行是否有误
  then
      echo "$1 Httpd is Running... " #若判断以上命令无误,输入用户传参数及检测结果
  else
      echo "$1 Httpd is Stoped..."  #若判断以上命令有误,输出用户传参数及检测结果
      exit 1
 fi
 }
 
 function panduan() {  #定义最后结果的函数
 if [ "$#" -ne 1 ]    #如果用户输入的传参数不是1
  then               #那么
       chuancan     #调用chuancan函数
 fi
       jc_url $1    #如果用户输入的传参数是1,那么就调用jc_url 函数
 }
 
 panduan $* #把命令行接收的所有参数传给函数内部
 
[root@localhost ~]# bash func2.sh www.baidu.com
www.baidu.com Httpd is Running...

实例四:检查Web服务是否启动

1、检查web服务是否启动

#!/bin/sh
. /etc/init.d/functions
start_nginx=/application/nginx/sbin/nginx
USAGE()
{      
   echo "USAGE $0 {start|stop|restart}"
   exit 1
}
if [ $# -ne 1 ]
   then
       USAGE
fi
if [ "$1" == "start" ]
   then
       $start_nginx
       action "start nginx" /bin/true
elif [ "$1" == "stop" ]
   then
       killall nginx
       action "stop nginx" /bin/true
 
elif [ "$1" == "restart" ]
   then
       pkill nginx
       sleep 2
       $start_nginx
       action "restart nginx" /bin/true
else
   USAGE
   exit 1
fi

十、expect - 免交互

使用expect创建脚本的方法:

1)定义脚本执行的shell

#!/usr/bin/expect

这里定义的是expect可执行文件的链接路径(或真实路径),功能类似于bash等shell功能

2)set timeout 30

   设置超时时间,单位是秒,如果设为timeout -1 意为永不超时

3)spawn 

   spawn 是进入expect环境后才能执行的内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。不能直接在默认的shell环境中进行执行主要功能,它主要的功能是给ssh运行进程加个壳,用来传递交互指令。

4)expect

   这里的expect同样是expect的内部命令

   主要功能:判断输出结果是否包含某项字符串,没有则立即返回,否则就等待一段时间后返回,等待时间通过timeout进行设置

5)send

   执行交互动作,将交互要执行的动作进行输入给交互指令

   命令字符串结尾要加上**"\r"**,如果出现异常等待的状态可以进行核查

6)exp_continue

   继续执行接下来的交互操作

7)interact

   执行完后保持交互状态,把控制权交给控制台;如果不加这一项,交互完成会自动退出

8)$argv

   expect 脚本可以接受从bash传递过来的参数,可以使用 [lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个……参数

实例一:无交互登录服务器创建新用户

#!/usr/bin/expect

# set host ip

set ipaddress "192.168.1.101"

#set loginuser

set name "root"

#set password

set passwd "1"

#set timeout

set timeout 30

#spawn

spawn ssh $name@$ipaddress

expect {

"yes/no" { send "yes\r";exp_continue }

"password" { send "$passwd\r" }

}


#interact

expect "#"

send "useradd user1\r"

send "pwd\r"

send "touch /opt/hello.txt\r"

send "exit\r"

expect eof

执行输出:

[root@localhost shell]# chmod a+x ssh.exp 
[root@localhost shell]# ./ssh.exp 
spawn ssh root@192.168.1.101
root@192.168.1.101's password: 
Last login: Thu Sep  7 09:38:16 2023 from 192.168.1.100
[root@Logserver ~]# useradd user1
[root@Logserver ~]# pwd
/root
[root@Logserver ~]# touch /opt/hello.txt
[root@Logserver ~]# exit
登出
Connection to 192.168.1.101 closed.

实例二:实现通过SSH自动登录对服务器进行批量管理

1、创建用户密码文件

[root@localhost shell]# cat user.txt 
192.168.1.101 1
192.168.1.102 1
192.168.1.103 redhat

2、创建无交互文件

[root@localhost shell]# cat exp2.exp 
#!/usr/bin/expect
# set host ip
set ipaddress [lindex $argv 0]

#set password
set passwd [lindex $argv 1]

#set timeout
set timeout 30
 
#spawn
spawn ssh root@$ipaddress
expect {

"yes/no" { send "yes\r";exp_continue }

"password" { send "$passwd\r" }

}

#interact

expect "#"

send "useradd zhangsan\r"

send "mkdir /tmp/hello\r"

send "exit\r"

expect eof

3、创建调用脚本

[root@localhost shell]# cat login.sh 
#!/bin/bash

for i in `awk '{print $1}' /root/shell/user.txt`

do

    j=`grep $i /root/shell/user.txt|awk '{print $2}'`

    expect /root/shell/exp2.exp $i $j

done

4、执行输出

[root@localhost shell]# ./login.sh 
spawn ssh root@192.168.1.101
root@192.168.1.101's password: 
Last login: Thu Sep  7 09:53:54 2023 from 192.168.1.100
[root@Logserver ~]# useradd zhangsan
[root@Logserver ~]# mkdir /tmp/hello
[root@Logserver ~]# exit
登出
Connection to 192.168.1.101 closed.
spawn ssh root@192.168.1.102
The authenticity of host '192.168.1.102 (192.168.1.102)' can't be established.
ECDSA key fingerprint is SHA256:29Hc2ezJCjBZVzmieSkg3XJTSpp1P5XlVuuteyQJnlE.
ECDSA key fingerprint is MD5:c3:45:25:c5:ed:b6:63:e8:1a:68:1d:ed:1a:02:34:c9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.102' (ECDSA) to the list of known hosts.
root@192.168.1.102's password: 
Last login: Thu Sep  7 09:43:44 2023
[root@localhost ~]# useradd zhangsan
[root@localhost ~]# mkdir /tmp/hello
[root@localhost ~]# exit
登出
Connection to 192.168.1.102 closed.
spawn ssh root@192.168.1.103
The authenticity of host '192.168.1.103 (192.168.1.103)' can't be established.
ECDSA key fingerprint is SHA256:xmISzP9LwjuCTnIUZ2cSv1qTYEr6MO4JCh906AvJNmc.
ECDSA key fingerprint is MD5:19:2a:77:6e:ca:cf:52:8f:c8:16:fa:d8:49:a4:0c:d1.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.103' (ECDSA) to the list of known hosts.
root@192.168.1.103's password: 
Last login: Tue Aug 22 04:37:05 2023
[root@es2 ~]# useradd zhangsan
[root@es2 ~]# mkdir /tmp/hello
[root@es2 ~]# exit
登出
Connection to 192.168.1.103 closed.

十一、数组

1.数组分类

  • 数值类型的数组
arr_number=(1 2 3 4 5);
  • 字符串类型数组
array_name=(value1 value2 ... valuen)

# 举例:
# 第一种:
arr_string=("abc" "edf" "sss");  或者 arr_string=('abc' 'edf' 'sss');
# 第二种:
user=(`cat /etc/passwd|cut -d: -f1`)
# 第三种:
stu=(lisa tom jarry "miss zhang")

2.读取数组

${array_name[index]}

3.定义数组(数值类型数组)declare -a

# 一次定义一个
arr[0]=1	# 0 是下标,对应的第一位数是 1
arr[1]=2	# 1 是下标,对应的数是 2

# 一次定义多个
arr1=(1 2 3 4)

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

# 读取数组中的元素
[root@itbest ~]# echo ${arr[0]}
1
[root@itbest ~]# echo ${arr[1]}
2

# 获取数组中的所有元素
[root@itbest ~]# echo ${arr[*]}  #获取数组中的所有元素
1 2 3 4

[root@itbest ~]# echo ${#arr[*]} #获取元素的个数
4


[root@itbest ~]# echo ${!arr[*]}  #获取元素的索引下标
0 1 2 3

[root@itbest ~]# declare -a  #查看普通数组的信息
...
declare -a arr='([0]="1" [1]="2" [2]="3" [3]="4")'

4.数组中替换、增加、删除元素的值

# 替换元素的值
[root@itbest ~]# arr2=(1 2 3 4)
[root@itbest ~]# echo ${arr2[*]}
1 2 3 4
[root@itbest ~]# arr2[1]=5		# 将下标为 1 的数字(2),替换为 5
[root@itbest ~]# echo ${arr2[*]}
1 5 3 4

*******************************************
*******************************************

# 增加新元素的值
[root@localhost shell]# arr2=(1 2 3 4)
[root@localhost shell]# arr2[6]=5		# 在下标为 6 的位置上增加数字 5
[root@localhost shell]# echo ${arr2[*]}
1 2 3 4 5

注意:当添加的元素的长度大于已存在的数组的长度时,默认值时添加在组数的最后

**************************************************************************************

# 删除数组中的值:unset
[root@localhost shell]# unset arr2[1]		# 清除下标为 【1】 处的值,也就是数字 2
[root@localhost shell]# echo ${arr2[*]}
1 3 4

[root@localhost shell]# unset arr2   # 清除整个数组的值
[root@localhost shell]# echo ${arr2[*]}

5.数组的切片

分片访问形式为:${数组名[@或*]:开始下标:结束下标},注意,不包括结束下标元素的值。

[root@localhost ~]# arr3=(1 2 3 4)
echo ${arr3[*]:1} 或 echo ${arr3[@]:1}			# 这里是分片访问从下标【1】开始的值
2 3 4

[root@localhost ~]# echo ${arr2[@]:1:2}			# 这里分片访问从下标为【1】开始,向后查看元素的个数为 2
2 3
[root@localhost ~]# echo ${arr2[*]:2:3}			# 这里分片访问从下标为【2】开始,向后查看元素的个数为 3
3 4

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

1).使用${array_name[@]} 或者 ${array_name[*]}都可以全部显示数组中的元素

2).同样道理${#array_name[@]} 或者  ${#array_name[*]}都可以用来求数组的长度

6.定义关联数组(字符串类型数组)declare -A

# 一次赋予一个值
declare -A ass_array1
ass_array1[name]='zhangsan'
ass_array1[age]=20

#执行结果
echo ${ass_array2[name]}
zhangsan

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

# 一次赋予多个值
declare -A ass_array2
ass_array2=([name]=lisi [age]=30)

#执行结果
echo ${ass_array2[name]}
lisi
declare -A    ##查看关联数组

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

echo ${ass_array2[name]}	##访问下标为name的元素
lisi
echo ${ass_array2[@]}		##获取所有的元素
lisi 30
echo ${#ass_array2[@]}		##获取元素的个数
2
echo ${!ass_array2[@]}		##获取索引
name age

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

总结:基本数组的索引是从0.....开始的,关联数组是可以自定义索引的。

实例一:学生信息查询系统

#!/bin/bash
for((i=0;i<3;i++))
do
read -p "输入第$((i+1))个人名:" name[$i]
read -p "输入第$[$i+1]个年龄:" age[$i]
read -p "输入第`expr $i + 1`个性别:" gender[$i]
done
   clear
  echo -e "\t\t\t学生信息查询系统"
while :
  do
read -p "输入要查询的姓名:" xm
[ $xm == "q" ] && exit
for((i=0;i<3;i++))
  do
  if [ "$xm" == "${name[$i]}" ];then
echo "姓名:${name[$i]} 年龄:${age[$i]} 性别:${gender[$i]}"
  fi
done
done

实例二:统计web网站的不同状态连接数

#!/bin/bash
declare -A array1

# 统计连接数个数
#states=$(netstat -antup |grep 80|awk -F" " '{print $6}')
states=$(ss -ant|grep 80|cut -d ' ' -f1)

 for i in $states
  do
     let array1[$i]++
  done

#遍历打印数组中的索引和元素的个数
 for j in ${!array1[@]}
  do
    echo $j:${array1[$j]}
  done

实例三:遍历列表中的水果

#!/bin/bash

# 定义一个数组变量
fruits=("苹果" "香蕉" "橙子" "葡萄" "西瓜")

# 循环遍历数组元素
for fruit in "${fruits[@]}"
do
    echo "水果: $fruit"
done

# 获取数组的长度
length=${#fruits[@]}
echo "数组的长度: $length"

# 获取数组的特定元素
echo "第一个水果: ${fruits[0]}"
echo "最后一个水果: ${fruits[length-1]}"

# 修改数组元素
fruits[2]="草莓"
echo "修改后的数组: ${fruits[@]}"