bash的变量与数组
变量:存储单个元素的内存空间; 也相当于是数组的0号索引。
数组:存储多个元素的连续的内存空间;
一、变量
1、介绍:
任何程序都需要变量。 变量是用来存储数据的。程序=指令+数据。
按照其变量是否需要严格定义其类型来划分 :
强类型语言: 简单讲就是严格区分变量类型,使用之前必须要声明一个变量的类型。如C、Python。
弱类型语言: 不强制区分变量的类型,在使用之前不用明确声明一个变量的类型,有默认的类型,一般默认是字符型的,用到时直接使用,直接赋值。 如:bash。
定义变量类型的作用:
数据存储格式;
数据的有效存储范围,有效取值范围都不一样,如 C语言的 整型,长整型。
比较机制不同,运算类型也不同。如字符 2加上3,等于 23. 而数值就是5.
不同类型的数据不能运算, 只能转换以后再运算。
变量的命令要求: 变量名其实就是指向的内存空间地址
只能使用数字、字母和下划线组成;
不能以数字开头;
不能使用程序中的关键字;
要见名知义。命名机制遵循某种法则;不能够使用程序的保留字,例如if, else, then, while等等;
2、定义变量:
本地变量:只对当前shell进程有效,对其子shell及其它shell都无效。
定义变量:[set]Var_name="Value"
引用变量:${Var_Name}
撤销变量:unset Var_Name
局部变量:仅对局部代码生效,只能在函数中使用。引用和撤销与上面相同
定义变量:local Var_Name="Value"
环境变量: 对当前shell及其子shell有效,所以在当前shell中所执行的脚本也可以使用这种变量,脚本的运行环境就是子shell。
定义变量:
(1) export name=value
(2) name=value ; export name 反过来也一样。
(3) declare -x name=value
(4) name=value ; declare -x name
位置变量:用以引用执行脚本或函数时的所调用的变量。
$1,$2......$n, 对应的就是第1、2、n个参数。数字两位的时候,要用{}括起来。
#!/bin/bash # echo "$1 $2 $3" star@sst-pp:/tmp$ bash test.sh user group shell user group shell
特殊变量:
$0: 脚本名称自身。
$?: 上一条命令的执行状态。状态返回值。状态用数字来表示: 0-255;0 成功;1-255: 失败。失败状态中: 1,2(命令参数错误),127(没有命令),255 是预留的。 我们可以手动定义其它的。
$$ 当前shell的PID
$!
$# 参数的数量
$* 所有参数
$@ 所有参数
bash内嵌的环境变量(通常为全大写字符):用于定义bash的工作环境
如:PATH, HISTFILE, HISTSIZE, HISTFILESIZE, HISTCONTROL, SHELL, HOME, UID, PWD, OLDPWD.....
查看环境变量:export, declare -x, printenv, env
撤销环境变量:unset name
只读变量:
定义变量:
declare -r name
readonly name
只读变量无法重新赋值,并且不支持撤销;存活时间为当前shell进程的生命周期,随shell进程终止而终止;
3、字符串变量修改:
只是输出,不是修改变量的值。通常用于赋值的时候。
变量是由bash提供的,所以一些操作也都支持glob通配符。
下面在普通变量上面用到的功能,在数组上大部分也都可以使用。
以前写的,不怎么样,但是稍微详细点:
http://fanqie.blog.51cto.com/9382669/1649669
下面的例子中用到的变量:
hi变量保存有"Hello World"
see变量保存有"/etc/systemd/system.conf"
字符串切片:
${var:offset:number}: 取字符串的子串, 变量:偏移数:取字符数
echo ${hi:3:2} 值:lo
切片也支持负数,取字符串的最右侧的几个字符:${var: -length}
注意:以负数取值,冒号后必须有一个空白字符;如:${arr: -8} 显示后面的8个字符。
echo ${hi: -2} 值:ld
也可以定义结束范围:echo ${arr:3:-9},3到-9之间的字符。3和-9只是用来标识位置的,而不是用来定义有哪些内容的,负数就是从右到左。而最终数据取值只能是从左到右。
echo ${hi:3:-2} 值:lo Wor
基于模式取子串:
${var#*word}:其中word是指定的分隔符;
功能:最短自左而右匹配,删除所有匹配到的字符。*是通配符。
echo ${hi#?e} 值:llo World
echo ${hi#*o} 值:World
echo ${hi#*o W} 值:orld
echo ${see#*/} 值:etc/systemd/system.conf
${var##*word}:其中word是指定的分隔符;
功能:最长自左而右匹配,删除所有匹配到的字符。*是通配符。
echo ${see##*/} 值:system.conf
${var%word*}:其中word是指定的分隔符;
功能:最短自右而左匹配,删除所有匹配到的字符。
echo ${see%/*} 值:/etc/systemd
这个完成了取路径的目录名,而上面的##完成了取路径基名。
${var%%word*}:其中word是指定的分隔符;
功能:最长自右而左匹配,删除所有匹配到的字符。
echo ${see%%/*} 值:
echo ${hi%%l*} 值:He
echo ${url%%:*} 值:https
#号标识数据的首部。 %用来标识尾部。
hi变量保存有"Hello World"
查找替换:PATTERN中可以使用glob通配符;
${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,并将其替换为SUBSTI所表示的字符串;
echo ${hi/l/L} 值:HeLlo World
echo ${hi/ll/LL} 值:HeLLo World
echo ${hi/*o/L} 值:Lrld
${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并将其全部替换为SUBSTI所表示的字符串;
echo ${hi//l/L} 值:HeLLo WorLd
${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;比/多了限制,只能从左每一个字符开始匹配成功。
echo ${hi/#l/L} 值:Hello World
echo ${hi/#H/L} 值:Lello World
echo ${hi/#*o/L} 值:Lrld
${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;与上面意思一样,只不过是从右到左。
查找删除:(see为/etc/systemd/system.conf)
${var/PATTERN}:删除以PATTERN为模式第一次匹配到的var字符串。这里不用替换了,下接删除。
与#不同的是,这个是定点删除,而#是范围删除。当然如果加上通配符也一样。
echo ${see/\/systemd} 值:/etc/system.conf
${var//PATERN} 删除以PATTERN为模式所有匹配到的var字符串。
${var/#PATTERN} 以左边界匹配。
${var/%PATTERN} 以右边界匹配。
字符大小写转换:
${var^^}:把var中的所有小写字符转换为大写;
${var,,}:把var中的所有大写字符转换为小写;
这个也可以用一个^或,来表示。 只转换一个字母。也可以用#或%来定义边界。
变量赋值:
${var:-VALUE}:如果var变量为空,或未设置,那么返回VALUE;否则,则返回var变量的值;
${var:=VALUE}:如果var变量为空,或未设置,那么返回VALUE,并将VALUE赋值给var变量;否则,则返回var变量的值;
${var:+VALUE}:如果var变量不空,则返回VALUE;
${var:?ERROR_INFO}:如果var为空,或未设置,那么返回ERROR_INFO为错误提示;否则,返回var值;
而VALUE不单单只能用字符,也可以用变量引用来表示数据。
变量中字符的个数:
${#var}
二、数组:
在普通变量上面用到的功能,在数组上大部分也都可以使用。
数组名:整个数组只有一个名字;
数组索引:编号从0开始;0是第一个索引。
bash-4及之后的版本开始支持"关联数组",也就是索引不是以数字表示,而是以自定义的字符串来表示。
声明数组:
declare -a NAME:声明索引数组; 这个不用显示的声明,赋值的同时就自动生成数组了。
declare -A NAME:声明关联数组; 这个需要先在赋值之前声明。
赋值方式:
一次只赋值一个元素;
ARRAY_NAME[INDEX]=value
只给0和5赋值了,其它索引都没有值。
一次赋值全部元素;会把上面单独定义的覆盖
可以看到,赋值索引是0,1,2 但是原来的5的值也没有了。
只赋值特定元素;这个也会覆盖数据。
ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...)
bash支持稀疏格式的数组;就是不按顺序来的索引。
read -a ARRAY_NAME
可以用read来获取输入为数组赋值。
也就只有第一种不会覆盖不同索引的数据。如:
数组的长度(数组中元素的个数):
${#ARRAY_NAME[*]}
echo ${#abc[*]} 5
与变量一样,只不过这里元素个数,那里是字符个数。当然也可以查看某元素的字符的个数。
echo ${#abc[1]} 3
${#ARRAY_NAME[@]}
这个与*是一样的。
引用数组中的元素:
${ARRAY_NAME[INDEX]}
注意:引用时如果只给数组名,表示引用下标为0的元素;
引用数组中的所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
数组元素切片:
${ARRAY_NAME[@]:offset:number}
offset:偏移的元素个数;
number:要取出的元素个数;省略number时,表示取偏移量之后的所有元素;
${arry[*]:3:2}
加上*来输出所有数据,再由3和2来定位哪个位置
如果不加*,数据只是一个字符块,会当做变量来操作。
变量也可以这样偏移,而且个数部分还可以用负数。我们上面变量部分已经试过了。
字符大小写转换
追加元素:
因为索引是从0开始,正好与个数少1。所以只要计算出元素个数,给个数赋值即可。
只能是非稀疏格式的数组,因为索引没有规律,可能有的索引比元素个数还要大。
ARRAY_NAME[${#ARRAY_NAME[*]}]=
红色部分是用来取出数组元素的个数。
删除数组中的某元素:
关联数组:
declare -A ARRAY_NAME
ARRAY_NAME=([index_name1]="value1" [index_name2]="value2" ...)
index_name就是自定义的字符串,它来做为索引,或许称为键。赋值方式与索引数组也没有什么不同。
本文出自 “大蕃茄” 博客,请务必保留此出处http://fanqie.blog.51cto.com/9382669/1741614
原文地址:http://fanqie.blog.51cto.com/9382669/1741614