Bash脚本编程之数组
数组简介
在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脚本编程之数组的更多相关文章
- 高级bash脚本编程(三)
高级bash脚本编程 知识点 compound 和 comparison -a 逻辑与 exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话,那么结果为真. -o 逻辑或 exp1 ...
- 高级Bash脚本编程(一)
高级Bash脚本编程 Bash 它是能力很强的计算机语言,被称为解释性语言或脚本语言,它可以调用所有的UNIX命令和工具再加上公共程序. Bash中的特殊字符 注释(#) (除#!外,#!是用于指定当 ...
- Bash脚本编程总结
bash脚本编程之用户交互: read [option]… [name …] -p ‘PROMPT’ -t TIMEOUT bash -n /path/to/some_script 检测脚本中的 ...
- Bash脚本编程之字符串处理
简介 其实这里说得字符串处理,对应的是bash官网中的[Shell Parameter Expansion],不过直接去看这部分内容实在是太难以理解了.就按照马哥所说的字符串处理会比较好理解,平常使用 ...
- SHELL脚本编程-普通数组(列表)和关联数组(字典)
SHELL脚本编程-普通数组(列表)和关联数组(字典) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组相关概述 变量: 存储单个元素的内存空间 数组: 存储多个元素的连续的 ...
- 脚本命令高级Bash脚本编程指南(31):数学计算命令
题记:写这篇博客要主是加深自己对脚本命令的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 高等Bash脚本编程指南(31):数学盘算命令 成于坚持,败于止步 操作数字 factor ...
- 高级Bash脚本编程指南(27):文本处理命令(三)
高级Bash脚本编程指南(27):文本处理命令(三) 成于坚持,败于止步 处理文本和文本文件的命令 tr 字符转换过滤器. 必须使用引用或中括号, 这样做才是合理的. 引用可以阻止shell重新解释出 ...
- 高级Bash脚本编程指南《Advanced Bash-Scripting Guide》 in Chinese
<Advanced Bash-Scripting Guide> in Chinese <高级Bash脚本编程指南>Revision 10中文版 在线阅读链接:http://ww ...
- 高级Bash脚本编程(二)
高级Bash脚本编程(二) 退出 退出状态码 退出:exit 被用来结束一个脚本,它也返回一个值,并且这个值会传递给脚本的父进程,父进程会使用这个值做下一步的处理. 每个命令都会返回一个退出状态码,成 ...
随机推荐
- 品优购详情页---产品细节模块product_detail
结构搭建 整个大盒子产品细节模块命名为: product_detail(不给高度,注意清除浮动带来的影响) 1号盒子命名为:aside(左侧浮动,有宽带不给高度) 2号盒子命名为:detail(右侧浮 ...
- 构建调试Linux内核网络代码的环境MenuOS系统
构建MenuOS系统 1.将指定文件拷贝到本地: git clone https://github.com/mengning/linuxnet.git 此过程可能需要输入github账号和密码. 2. ...
- 09-kubernetes configMap secret
目录 配置容器化应用配置的方式 命令创建和测试configMap 创建一个Pod 挂在测试 命令行文件类创建方式 创建Pod测试 创建后测试 贴近实际进行测试 创建后测试 secret 举例测试 ge ...
- WebGPU学习(二): 学习“绘制一个三角形”示例
大家好,本文学习Chrome->webgl-samplers->helloTriangle示例. 准备Sample代码 克隆webgl-samplers Github Repo到本地. ( ...
- 一个有意义的Day类
早晨去单位的路上听到电台里在说“Everyday is a new chance to change your life”,正好最近在学Python类的使用方法,于是我编了一个关于Day的类,以供参考 ...
- Feign超时设置
转-原文:https://xli1224.github.io/2017/09/22/configure-feign/ 在分析 Feign 源码的时候,我们看到 Feign 构建代理对象是分了几层的,一 ...
- vscode从听说到使用,vetur,prettier,htmljscssPrettify踩坑指南。
今天基于vue-cli(2.9.3)构建一个新的项目.我用的sublime,es6的代码格式要与公司格式兼容.采用了vue-cli自带的eslint后,有一些不统一的部分需要修改.先看看sublime ...
- Spring Cloud第五篇 | 服务熔断Hystrix
本文是Spring Cloud专栏的第五篇文章,了解前四篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Clo ...
- 压缩感知重构算法之OMP算法python实现
压缩感知重构算法之OMP算法python实现 压缩感知重构算法之CoSaMP算法python实现 压缩感知重构算法之SP算法python实现 压缩感知重构算法之IHT算法python实现 压缩感知重构 ...
- DAO模式多表联查
student类: package com.myschool.entity; public class student{ private int studentno; //学号 private S ...