数组简介

在bash脚本编程当中,变量是存储单个元素的内存空间;而数组是存储多个元素的一段连续的内存空间。

数组由数组名和下标构成,如下。

ARRAY_NAME[SUBSCRIPT]

数组按照下标的类型可分为两种:

  • 索引(indexed)数组:下标为0、1、2等非负整数。
  • 关联(associative)数组:下标为用户自定义的字符串。

数组的操作

声明

索引数组可以不声明直接使用;而关联数组如果不声明直接使用的话,会被认为是索引数组,即使它的下标是字符串。

索引数组的声明方式。

# declare -a ARRAY_NAME

关联数组的声明方式。

# declare -A ARRAY_NAME

赋值

一次只赋值一个元素。

# ARRAY_NAME[SUBSCRIPT]=VALUE

一次赋值全部元素。

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

一次赋值多个可以是不连续的元素。

# ARRAY_NAME = ([] = "VAL1" [] = "VAL3")

像这种不要求元素必须依次存在的数组(即可以在没有A[1]和A[2]的时候就赋值A[3]),叫做稀疏格式数组。因此,bash支持稀疏格式的数组。

读取标准输入赋值数组。

# read -a ARRAY_NAME

在输入的时候,以空格作为元素的分隔符,以回车键结束元素的赋值。

向数组的末尾追加元素。

ARRAY_NAME[${#ARRAY_NAME[@]}]=VALUE 

或者

ARRAY_NAME+=(VALUE)

引用

引用单个数组元素。

${ARRAY_NAME[SUBSCRIPT]}

如果省略SUBSCRIPT,那么就等同于SUBSCRIPT=0。即以下两个引用是相同的。

${ARRAY_NAME[]}
${ARRAY_NAME}

下标可以是一个变量,当下标是一个变量的时候,可以省略掉展开下标变量字符“$”。即${array[$var]}=${array[var]}。

[root@c7-server ~]# declare -a name=(bu jing yun)
[root@c7-server ~]# echo ${name[*]}
bu jing yun
[root@c7-server ~]# declare -i a= b= c=
[root@c7-server ~]# echo ${name[$a]}
bu
[root@c7-server ~]# echo ${name[$b]}
jing
[root@c7-server ~]# echo ${name[$c]}
yun
[root@c7-server ~]# echo ${name[a]}
bu
[root@c7-server ~]# echo ${name[b]}
jing
[root@c7-server ~]# echo ${name[c]}
yun

引用数组的所有元素。正常情况下,二者没有区别,只有当被双引号包裹的时候,“@”被展开为每个元素为一个独立的单词;“*”被展开为所有元素为一个统一的单词。

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

引用数组元素的长度。

${#ARRAY_NAME[SUBSCRIPT]}

引用数组的长度,即数组的元素个数。

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

引用数组的部分元素(切片)。

${ARRAY_NAME[@]:OFFSET:NUMBER}
${ARRAY_NAME[*]:OFFSET:NUMBER}

OFFSET:偏移,表示偏移/跳过数组中的前几个元素。

NUMBER:表示偏移后取几个元素。

如果省略了NUMBER,并且OFFSET的值为“ -n”(注意,-n的左边有空格),则表示引用倒数的n个元素。

截止目前我们引用的都是数组的值,如果我们想引用数组的下标的话,可以使用:

${!ARRAY_NAME[@]}
${!ARRAY_NAME[*]}

删除

删除数组元素。

# unset ARRAY_NAME[SUBSCRIPT]

删除数组。

# unset ARRAY_NAME

数组示例

定义一个索引数组,逐一赋值数组元素。

[root@c7-server ~]# declare -a my_array
[root@c7-server ~]# my_array[]=zhang
[root@c7-server ~]# my_array[]=wen
[root@c7-server ~]# my_array[]=long

根据数组下标获取数组元素。留意我们上文说的,当引用数组不带下标的时候,等同于引用${ARRAY_NAME[0]}。

[root@c7-server ~]# echo ${my_array}
zhang
[root@c7-server ~]# echo ${my_array[]}
zhang
[root@c7-server ~]# echo ${my_array[]}
wen
[root@c7-server ~]# echo ${my_array[]}
long

引用数组中的所有元素,顺便测试一下“@”和“*”的区别。注意,这个区别,仅在${my_array[@]}或者${my_array[*]}被双引号包裹的情况下才会出现。

[root@c7-server ~]# echo ${my_array[@]}
zhang wen long
[root@c7-server ~]# echo ${my_array[*]}
zhang wen long
[root@c7-server ~]# for i in "${my_array[@]}"; do echo $i; done
zhang
wen
long
[root@c7-server ~]# for i in "${my_array[*]}"; do echo $i; done
zhang wen long

引用数组个数。

[root@c7-server ~]# echo ${#my_array[@]}

[root@c7-server ~]# echo ${#my_array[*]}

引用数组中元素的个数。

[root@c7-server ~]# echo ${my_array[]}
zhang
[root@c7-server ~]# echo ${#my_array[]}

接下来演示其他几种不同的赋值方式,操作前可先删除数组。

[root@c7-server ~]# unset my_array
[root@c7-server ~]# my_array=([]=zhang []=wen []=long)
[root@c7-server ~]# echo ${my_array[@]}
zhang wen long
[root@c7-server ~]# unset my_array
[root@c7-server ~]# read -a my_array
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun

数组元素去子串(substring),即切片。

[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# echo ${my_array[@]::}
Thu Fri
[root@c7-server ~]# echo ${my_array[@]::}
Wed Thu Fri
[root@c7-server ~]# echo ${my_array[@]: -}
Fri Sat Sun

数组元素追加。

[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# my_array+=(ddd)
[root@c7-server ~]# my_array[${#my_array[@]}]=eee
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun ddd eee

引用数组的下标(subscript)。个人感觉引用数组下标在关联数组中比较有用,在索引数组中用处不大。

[root@c7-server ~]# echo ${!my_array[@]}

[root@c7-server ~]# unset my_array
[root@c7-server ~]# declare -A my_array
[root@c7-server ~]# my_array=([name]=zwl [age]= [sex]=male)
[root@c7-server ~]# echo ${my_array[@]}
zwl male
[root@c7-server ~]# echo ${!my_array[@]}
name age sex

练习题

题一:生成10个100以内的非负整数并存入数组当中,对其进行排序然后输出最大值和最小值。

这道题,涉及到算法中的冒泡排序,可以参考一下《冒泡排序_百度百科》中的概念解释,以及《1.1 冒泡排序 | 菜鸟教程》中的图示,这个GIF图真的超棒!

按照升序排序后,最大值和最小值取头尾即可。

代码示例。

#!/bin/bash

declare -a rand
declare -i rand_length var
for i in {..}; do
rand[$i]=$((RANDOM%))
done
echo -e "The original array is \t${rand[*]}."
rand_length=${#rand[*]}
#echo $rand_length for i in $(seq $((rand_length-)) | sort -nr); do
for((j=;j<$i;j++)); do
if [ ${rand[j]} -gt ${rand[((j+))]} ]; then
var=${rand[j]}
rand[j]=${rand[j+]}
rand[j+]=$var
fi
done
#echo ${rand[*]}
done echo -e "The last array is \t${rand[*]}."
echo "The min of the array is ${rand[0]}."
echo "The max of the array is ${rand[-1]}."

结果演示。

[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .
[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .
[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .

看懂代码以后,我们可以调整一下echo语句,就可以看到每次循环排序的结果。

The original array is              .

10 21 34 36 50 52 57 68 83 98

从结果中我们也会发现,除非是刚好是倒序的情况,否则在循环的中途就可以排序完成了。

这个脚本,个人觉得还是会稍微难点的,尤其是对于算法基础薄弱且非编程的人员,我也是Google后才知道结果的,真的搞不懂的同学,不必纠结,将来再补算法即可,这篇随笔主要是了解数组的。

题二:定义一个数组,数组元素为/var/log/目录下所有以.log结尾的文件的文件名;统计下标为偶数的文件的行数并求和。

#!/bin/bash

declare -a filePool=(/var/log/*.log)
declare -i sum=0
declare -i line for i in $(seq 0 $((${#filePool[*]}-1))); do
if [ $((i%2)) -eq 0 ]; then
line=$(wc -l ${filePool[i]} | cut -d " " -f 1)
((sum+=line))
fi
done echo "The sum of lines which meet the conditions is $sum."

Bash脚本编程之数组的更多相关文章

  1. 高级bash脚本编程(三)

    高级bash脚本编程 知识点 compound 和 comparison -a 逻辑与 exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话,那么结果为真. -o 逻辑或 exp1 ...

  2. 高级Bash脚本编程(一)

    高级Bash脚本编程 Bash 它是能力很强的计算机语言,被称为解释性语言或脚本语言,它可以调用所有的UNIX命令和工具再加上公共程序. Bash中的特殊字符 注释(#) (除#!外,#!是用于指定当 ...

  3. Bash脚本编程总结

    bash脚本编程之用户交互: read [option]… [name …]  -p ‘PROMPT’  -t TIMEOUT bash -n /path/to/some_script  检测脚本中的 ...

  4. Bash脚本编程之字符串处理

    简介 其实这里说得字符串处理,对应的是bash官网中的[Shell Parameter Expansion],不过直接去看这部分内容实在是太难以理解了.就按照马哥所说的字符串处理会比较好理解,平常使用 ...

  5. SHELL脚本编程-普通数组(列表)和关联数组(字典)

    SHELL脚本编程-普通数组(列表)和关联数组(字典) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组相关概述 变量: 存储单个元素的内存空间 数组: 存储多个元素的连续的 ...

  6. 脚本命令高级Bash脚本编程指南(31):数学计算命令

    题记:写这篇博客要主是加深自己对脚本命令的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 高等Bash脚本编程指南(31):数学盘算命令 成于坚持,败于止步 操作数字 factor ...

  7. 高级Bash脚本编程指南(27):文本处理命令(三)

    高级Bash脚本编程指南(27):文本处理命令(三) 成于坚持,败于止步 处理文本和文本文件的命令 tr 字符转换过滤器. 必须使用引用或中括号, 这样做才是合理的. 引用可以阻止shell重新解释出 ...

  8. 高级Bash脚本编程指南《Advanced Bash-Scripting Guide》 in Chinese

    <Advanced Bash-Scripting Guide> in Chinese <高级Bash脚本编程指南>Revision 10中文版 在线阅读链接:http://ww ...

  9. 高级Bash脚本编程(二)

    高级Bash脚本编程(二) 退出 退出状态码 退出:exit 被用来结束一个脚本,它也返回一个值,并且这个值会传递给脚本的父进程,父进程会使用这个值做下一步的处理. 每个命令都会返回一个退出状态码,成 ...

随机推荐

  1. Windows Server 2012R2 DHCP服务介绍及搭建 转载

    转载链接:https://blog.csdn.net/KamRoseLee/article/details/79251830   一.什么是DHCP DHCP(DynamicHost Configur ...

  2. docker概念

    一.docket概述 什么是docker? 为什么docker会出现 一款产品从开发到上线,从操作系统,到运行环境,再到应用配置.作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不 ...

  3. Django REST framework(DRF)

    Django REST framework(DRF) FBV与CBV CBV源码分析 Restful接口规范 DRF简单配置使用和源码解析 DRF序列化器 DRF10大接口 DRF视图集 三大组件 j ...

  4. react简单的tab切换 (styled-components)

    其实,在我们日常的编程当中,经常会碰到tab切换的模块,那么,实现他的方法也有很多中,下面是一款简单,容易理解的react tab切换方法. 通过设置state中的current 属性去控制tab 和 ...

  5. 学习WebFlux时常见的问题

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾一下上篇我对WebFlux的入门,如果没读过 ...

  6. 基于JDK1.8的JVM 内存结构【JVM篇三】

    目录 1.内存结构还是运行时数据区? 2.运行时数据区 3.线程共享:Java堆.方法区 4.线程私有:程序计数器.Java 虚拟机栈.本地方法栈 5.JVM 内存结构总结 在我的上一篇文章别翻了,这 ...

  7. TypeScript躬行记(1)——数据类型

    TypeScript不仅支持JavaScript所包含的数据类型,还额外扩展了许多实用的数据类型,例如枚举.空值.任意值等. 一.JavaScript的数据类型 JavaScript的数据类型包括6种 ...

  8. 微信小程序——动态修改页面数据(和样式)及参数传递

    1.1.1动态修改页面数据 在小程序中我们经常要动态渲染数据,对于新手而言我们常常遇到修改的数据在控制台显示和页面显示不一致,因为我们用“=”修改数据的,这种是可以修改,但无法改变页面的状态的,还会造 ...

  9. Spring boot如何快速的配置多个Redis数据源

    简介 redis 多数据源主要的运用场景是在需要使用多个redis服务器或者使用多个redis库,本文采用的是fastdep依赖集成框架,快速集成Redis多数据源并集成lettuce连接池,只需引入 ...

  10. 从React 编程到"好莱坞"

    目录 概念 面向流设计 异步化 响应式宣言 参考文档 概念 Reactive Programming(响应式编程)已经不是一个新东西了. 关于 Reactive 其实是一个泛化的概念,由于很抽象,一些 ...