数组ARRAY
变量:存储单个元素的内存空间
数组:存储多个元素的连续的内存空间,相当于多个变量的集合,元素编号支持稀疏格式,即索引编号不连续。
高级变量用法 - 有类型变量
Shell变量一般是无类型的,但是bash提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
declare [OPTION] 变量名
-r 声明或显示只读变量
-i 声明或显示整数型变量
-a 声明或显示索引数组
-A 声明或显示关联数组
-f 显示系统的所有函数
-F 仅显示所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母 declare –l var=UPPER
-u 声明变量为大写字母 declare –u var=lower
声明数组:
declare -a ARRAY_NAME //声明索引数组,元素编号只能是数字,从0开始
declare -A ARRAY_NAME //声明关联数组,元素编号可以自定义格式,需bash4.0以上的版本才支持
declare -i ARRAY_NAME //声明整数数组,元素变量只支持整数值
declare -r ARRAY_NAME //声明只读数组
declare -l ARRAY_NAME //转换数组为小写
declare -u ARRAY_NAME //转换数组为大写
声明数组
declare -a user //声明索引数组
declare -a //查看索引数组
declare -A user //声明关联数组
declare -A
declare -i //查看所有整数数组
数组元素赋值,索引数组的编号只支持数字,而且是从0开始
1.单个元素赋值
user[0]="user0"
user[1]="user1"
user[2]="user2"
user[3]="user3"
user[4]="user4"
user[5]="user5"
2.多个元素赋值
user=("usera" "userb" "userc" "userd" ...)
3.只赋值特定元素,则其他未赋值的元素值为空,如user[1]就为空
user=([0]="usera" [3]="userc"...)
4.交互式赋值
read -a user
a b c d e //输入的参数以空格隔开
a\ b cc ee //如果输入的参数包含空格则需要转义,如"a b".
显示或引用数组
declare -a
echo $user //显示第一个元素,相当于echo ${user[0]}
echo ${user[0]}
echo ${user[2]}
echo ${user[3]}
echo ${user[*]}
echo ${#user[*]}
取消数组或元素
unset user[2] //取消数组元素2
unset user //取消整个数组
声明关联数组
declare -A user
数组元素赋值,编号支持字母,数字或单词
user[a]=usera
user[b]=userb
user[2]=userc
user[abc]=userabc
查看数组元素值
declare -A|tail -1
echo ${user[a]}
echo ${user[2]}
echo ${user[abc]}
取消数组或元素
unset user[a]
unset user
批量定义数组元素,未声明数组类型则默认为索引数组
user=(usera userb userc userd)
echo ${user[3]}
num=({1..10})
echo ${num[8]}
echo ${num[*]} //显示数组中的所有元素,*也可用@代替
echo ${#num[*]} //显示数组的元素个数,*也可用@代替
file=({/app/bin/*.sh})
echo ${file[3]}
echo ${file[@]} //显示数组的所有元素
echo ${#file[@]} //显示数组的元素个数
num=({1..10})
for((i=0;i<${#num[@]};i++));do echo num is ${num[$i]};done
unset num[2]
for((i=0;i<${#num[@]};i++));do echo num is ${num[$i]};done //稀疏数组显示会有问题,即不会自动递归填补空值
num[2]=3 //添加缺少的数组元素
数组元素处理
数组切片:${ARRAY[@]:offset:number}
offset: 要跳过的元素个数
number: 要取出的元素个数
num=({1..10})
echo ${num[*]:2:5} //跳过前2个,取出5个元素
3 4 5 6 7
echo ${num[*]:3} //跳过前3个,取出之后的所有元素
4 5 6 7 8 9 10 11 12 13
seq 10 //显示1..10,默认从1开始到指定数字
seq 2 5 //显示2,3,4,5,显示从起始值到结束值之间的数字
seq 1 2 10 //显示1,3,5,7,9,格式为起始值,增量值,结束值
num=10;seq 0 2 $[$num-1]
echo {1..10..2} //显示1,3,5,7,9,格式为起始值,结束值,增量值
num=({1..10..2})
向数组中追加元素:ARRAY[${#ARRAY[*]}]
num=({1..10})
echo ${sum[10]} 值为空
num[${#num[*]}]=11 //追加数组元素,追加到所有数组元素的最后
echo ${sum[10]} 显示追加的元素值11
num[${#num[*]}]=12 //可追加多次
num[${#num[*]}]=13
删除数组中的某元素,会导致稀疏格式:unset ARRAY[INDEX]
unset num[8]
删除整个数组:unset ARRAY
unset num
字符串处理
man bash 搜索\$\{parameter\} //查看命令帮助
取字符值
注意:取值时,正数前面不需要加空格,负数前面需要加一个空格。
$alp 或${alp} 显示字符串内容
${#var} 显示字符串的长度
${var:offset:0} 显示所有字符串
${var:offset} 跳过前几个字符,取后面的所有字符
${var:offset:length} 跳过前offset个字符,取其后面的length个字符
${var:offset:-length} 跳过前offset个字符和后length个字符,显示中间的内容
${var: -length} 取字符串的最右侧几个字符。注意:冒号后有一个空格,如${num: -3}
${var: -length: -offset} 取出字符串的最右侧几个字符,然后在此基础上,跳过后几个字符,显示剩余字符。
${var: -length:length} 取出字符串的最右侧的几个字符,然后在此基础上,取出length个字符
alp=`echo {a..z}|tr -d " "` //显示字符串abcdefg..xyz
echo $alp //显示字符串
echo ${#alp} //查看字符串的长度,即字符个数
echo ${alp:0} //显示所有字符串
echo ${alp:3} //跳过前3个字符,显示后面所有字符
echo ${alp:3:5} //跳过前3个字符,取其后面的5个字符,显示defgh
echo ${alp:3:-5} //跳过前3个字符和后5个字符,显示中间的内容
echo ${alp: -3} //显示最后3个字符,即xyz
echo ${alp: -3: -2} //先取出最右侧的3个字符,然后再跳过后2个字符,即最后显示字符x。
echo ${alp: -3:2} //先取出最右侧的3个字符,然后取出前2个字符,即显示为xy
删除字符
${var#word} //删除指定的前缀字符
${var#*word} //从左往右,匹配删除word本身及word之前的所有字符
${var##*word} //贪婪模式,匹配删除最后的word本身及之前的所有字符
${var%word} //删除指定的后缀字符
${var%word*} //从右往左,匹配删除word本身及word之后的所有字符。注意写法*号在word右边
${var%%word*} //贪婪模式,匹配删除最后的word本身及之后的所有字符
url=http://www.baidu.com:80
echo ${url#http://}
echo ${url#*:}
echo ${url##*:} //取端口号
echo ${url%:80}
echo ${url%:*} //取网址
echo ${url%%:*} //取协议
取路径和文件名
file="/var/log/messages"
echo ${file#*/} //取相对路径:var/log/messages
echo ${file##*/} //取文件名:messages,相当于basename
echo ${file%/*} //取父目录:/var/log,相当于dirname
查找替换
${var/pattern/string} //查找并替换第一次被匹配到的字符
${var//pattern/string} //查找并替换所有被匹配到的字符
${var/#pattern/string} //查找并替换行首匹配到的字符
${var/%pattern/string} //查找并替换行尾匹配到的字符
a=abcabc
echo ${a/b/g} //匹配替换一次,显示为agcabc
echo ${a//a/g} //匹配替换所有,显示为gbcgbc
echo ${a/#a/g} //匹配替换行首,显示为gbcabc
echo ${a/%c/g} //匹配替换行尾,显示为abcabg
url=http://www.baidu.com:80
echo ${url/%80/8080} //替换端口为8080
查找删除
${var/pattern} //查找并删除第一次匹配到的字符
${var//pattern} //查找并删除所有匹配到的字符
${var/#pattern} //查找并删除行首匹配到的字符
${var/%pattern} //查找并删除行尾匹配到的字符
a=abcabc
echo ${a/b} //显示为acabc
echo ${a//b} //acac
echo ${a/#a} //bcabc
echo ${a/%c} //abcab
转换大小写
${var^} //转换首字母为大写
${var^^} //把所有小写字母转换为大写
${var,} //转换首字母为小写
${var,,} //把所有大写字母转换为小写
a=abcabc
b=ABCABC
echo ${a^^} //小写转大写
echo ${b,,} //大写转小写
变量赋值检测
${var:-word} 如果var值为空或未设置,则返回word值,否则返回之前设置的var值
${var:+word} 如果var值为空或未设置,则返回为空,否则返回word值
${var:=word} 如果var值为空或未设置,则设置var值为word值,即定义变量值,否则返回之前设置的var值
${var:?word} 如果var值为空或未设置,则返回错误信息word,否则返回之前设置的var值
a=abc
b=
echo ${a:-c} 显示abc
echo ${b:-c} 显示c
echo ${a:+c} 显示c
echo ${b:+c} 显示为空
echo ${a:=c} 显示为abc
echo ${b:=c} 显示为c,并赋值给b
echo $b 显示为c,即上述赋值生效
unset b
echo ${a:?c} 或 echo ${a:?} 显示abc
#echo ${b:?} 未定义则默认显示如下的错误信息
-bash: b: parameter null or not set
#echo ${b:?this is error} 错误信息显示为自定义的语句或值
-bash: b: this is error
#echo ${b:?100}
-bash: b: 100
为所有脚本使用一个独立的变量文件,统一所有变量,类似于独立的函数文件
echo "name=user1" > var //将所有的变量都放到文件var中,以后的脚本都调用此变量文件即可
vi a.sh
#!/bin/bash
#a.sh
. var
echo your name is $name
执行./a.sh
eval 命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量
cmd=whoami
# echo $cmd
whoami
# echo `$cmd`
# $cmd
# eval $cmd
echo `whoami`
eval whoami
echo `ll`
eval ll //保留源命令属性,显示的格式等
n=10
echo {1..$n} //无法正常显示序列
eval echo {1..$n} //正常显示数字序列1-10
间接变量引用
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
两种方式:eval var1=\$$var2 或 var1=${!var2}
a=b
b=c
eval echo \$$a //显示为c
echo ${!a} //显示为c