一 Shell 数组
数组中可以存放多个值,Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。
与大部分编程语言类似,数组元素的下标由0开始
Shell 数组用括号()来表示,元素用"空格"符号分割开
二 数组定义方法
(1)逐个赋值
涉及知识点
(0)获取数组'某个index'的元素 '-->补充':echo ${names:0}
(1)获取数组里面'元素的个数'
(2)获取数组'全部的元素'
(3)获取数组某个'元素的长度'
补充:数组*和@的区别
'*'当变量加上"" 会当成'一串字符串'处理
'@'变量加上"" 依然当做数组处理,所有的参数默认被IFS'分割成'数组的每个元素
在'数组遍历'的时候能体会二者的区别
(2)全数组初始化
说明:默认是以空格分割,没有下标默认是首元素
说明:这种分行的方式可行,可读性强。
(3)间隔索引
#必须先声明字典
declare -A dic
dic=([key1]="value1" [key2]="value2" [key3]="value3")
字典'python角度'的赋值
说明:元素的个数以'实际为准',而'不是以最后元素'的index进行判断的
(4)数组的另外两种定义
declare -a arryy '一般数组',下标'index'是数字
declare -A array '关联数组',下标是'字符串',类似'key:value'
键盘读取输入,默认以'空格隔开','换行表示结束'
read -a array
(5)动态生成数组
需求:把一个以IFS分割的字符串转换成数组
方式1
说明:默认是以空格进行分割的!
'替换' -->echo ${arr[@]}
另一种策略:可以整个模块'设置到一个函数里面',然后'IFS变量通过local定义为局部变量'
方式2:字符串转换为数组 推荐
${string//substring/replacement} 使用$replacement,"替换所有匹配"的$substring
(6)数组调试
二 数组的各项骚操作
(1)数组的切片
begin"索引开始":length"连续的长度"
含义:从第'n'个元素开始,打印'm'个元素
(2)数组遍历
names=(A B C D)
# (1)无下标的遍历数组
for i in "${names[@]}"
do
echo ${i}
done
for j in "${names[*]}"
do
echo $j
done
数组操作命令 | 含义 |
---|---|
${#array[@]} | 取数组元素的个数 |
${#array[*]} | 取数组元素的个数 |
${array[*]} | 取所有数组的元素 |
${array[@]} | 取所有数组的元素 |
${!array[@]} | 取数组下标的值 |
${array[@]:n:m} | 从数组n位置开始取m个元素-->切片 |
array_new=(${array1[@]} ${array2[@]}) | 数组合并:将array1和array2合并然后赋值给array_new |
array=($(echo ${ayyary[@]} | sed ‘s/ /\n/g’ |sort )) | uniq | 对数组进行去重排序,详细解释 |
if echo “${array[@]}” | grep -w “item_1” &>/dev/null; then echo "Found" fi | 判断item_1是否在'in'array中 |
补充:删除数组某个元素 unset array[index]
(3)关联数组
由于shell的的数组只支持一维数组,并且并没有map这种数据结构也,我们使用关联数组来模拟map的效果
declare -A map
map['JAVA_CMD']='/usr/bin/java'
map['GO_CMD']='/usr/bin/go'
map['Python_CMD']='/usr/bin/python'
# 遍历map,此map其实就是数组
for key in "${!map[@]}";do
echo "key: ${key}" "value: ${map[${key}]}"
done
需求:'不输出'数组的某个元素
for key in ${!ipMap[@]}
do
if [ B != $key ];then
echo ${ipMap[B]}
fi
done
选项 | 含义 |
---|---|
-a name | 声明变量为普通数组 |
-A name | 声明变量为关联数组(支持索引下标为字符串) |
-f [name] | 列出之前由用户在脚本中定义的函数名称和函数体 |
-F [name] | 仅列出自定义函数名称 |
-g name | 在 Shell 函数内部创建全局变量 |
-p [name] | 显示指定变量的属性和值 |
-i name | 将变量定义为整数型 |
-r name[=value] | 将变量定义为只读(不可修改和删除-->unset),等价于 readonly name |
-x name[=value] | 将变量设置为环境变量,等价于 export name[=value]。 |
应用场景:处理配置文件时,需要把解析到的配置文件保存到数组中,方便后续的使用
理解:CURD对应的操作!
(4)二维数组
7 #****************************************************
8 a=('1 2 3' '4 5 6' '7 8 9')
9
10 # 由于默认是IFS作为分割符
11
12 # (1)定义整数-->数组的个数-->适用普通数组
13 declare -i num=${#a[@]}-1
14
15 # (2)双层for循环实现-->多行注释
16 :<<!
declare -i num=0
17 for i in `seq 0 $num `
18 do
19 for j in "${a[${i}]}"
20 do
num++
21 echo ${j}
22 done
23 done
echo ${num}
24 !
25 # (3)方式2-->适用所有的数组
26 for i in ${!a[@]}
27 do
28 echo $i
29 done
效果展示
补充:上面多行注释如果用num变量来统计内存循环的次数会发现循环了三次,说明shell确实只能识别一维数组。
方式2:另外一种不是特别高明的设计-->arry+number形式或其他有迹可寻找(字母)
报错原因:shell只会进行一次扫描和变量替换,所以不能引用变量作为变量名的一部分
引申出:eval(安全问题),它的作用是先扫描改行并完成所有的变量替换, 然后执行替换后的命令
1.xss攻击
2.sql注入
解释:第一个$前要用\,向eval表明这是一个普通的$字符,不需要理解为变量,否则会eval会把$a当成一个变量
关注输出结果