bash的变量与数组html
变量:存储单个元素的内存空间; 也至关因而数组的0号索引。
数组:存储多个元素的连续的内存空间;shell
1、变量数组
一、介绍:bash
任何程序都须要变量。 变量是用来存储数据的。程序=指令+数据。
按照其变量是否须要严格定义其类型来划分 :ide
强类型语言: 简单讲就是严格区分变量类型,使用以前必需要声明一个变量的类型。如C、Python。函数
弱类型语言: 不强制区分变量的类型,在使用以前不用明确声明一个变量的类型,有默认的类型,通常默认是字符型的,用到时直接使用,直接赋值。 如:bash。ui
定义变量类型的做用:google
数据存储格式;url
数据的有效存储范围,有效取值范围都不同,如 C语言的 整型,长整型。spa
比较机制不一样,运算类型也不一样。如字符 2加上3,等于 23. 而数值就是5.
不一样类型的数据不能运算, 只能转换之后再运算。
变量的命令要求: 变量名其实就是指向的内存空间地址
只能使用数字、字母和下划线组成;
不能以数字开头;
不能使用程序中的关键字;
要见名知义。命名机制遵循某种法则;不可以使用程序的保留字,例如if, else, then, while等等;
二、定义变量:
本地变量:只对当前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, 对应的就是第一、二、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
$! Shell最后运行的后台进程的PID
$# 参数数量
$* 全部参数
$@ 全部参数
$- 使用Set命令设定的Flag一览
下面摘自:http://blog.chinaunix.net/uid-26527046-id-3336483.html
$* :
位置参数从参数 1 开始。若是在双引号中进行扩展,则扩展就是一个词,由 IFS 特殊变量的第一个字符
将参数分开,若是 IFS 为空,则没有间隔空格。IFS 的默认值是空白、制表符和换行符。若是没有设置 IFS,
则使用空白做为分隔符(仅对默认 IFS 而言)。
$@ :
位置参数从参数 1 开始。若是在双引号中进行扩展,则每一个参数都会成为一个词,所以 “$@” 与
“$1” “$2” 等效。若是参数有可能包含嵌入空白,那么您将须要使用这种形式。
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进程终止而终止;
三、字符串变量修改:
只是输出,不是修改变量的值。一般用于赋值的时候。
变量是由bash提供的,因此一些操做也都支持glob风格的通配符。
下面在普通变量上面用到的功能,在数组上大部分也均可以使用。
之前写的,不怎么样,可是稍微详细点:
http://fanqie.blog.51cto.com/9382669/1649669
下面的例子中用到的变量:
hi变量保存有"Hello World"
see变量保存有"/etc/systemd/system.conf"
字符串切片:
${var:offset:number}: 取字符串的子串, 变量:偏移数:取字符数。与数组索引同样,0表示第一个元素,只不过在变量里第一个元素就是表示第一个字符。
echo ${hi:3:2} 值:lo 从第四个字符开始,取2个。
切片也支持负数,取字符串的最右侧的几个字符:${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}
2、数组:
在普通变量上面用到的功能,在数组上大部分也均可以使用。
数组名:整个数组只有一个名字;
数组索引:编号从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。因此只要计算出元素个数,给个数赋值便可。
只能是非稀疏格式的数组,由于稀疏格式是没有顺序的,可能有的索引位是8,但元素的个数却只有2个,这样追加追加,一下子就把8给覆盖了。
ARRAY_NAME[${#ARRAY_NAME[*]}]=
红色部分是用来取出数组元素的个数。
删除数组中的某元素:
关联数组:
declare -A ARRAY_NAME
ARRAY_NAME=([index_name1]="value1" [index_name2]="value2" ...)
index_name就是自定义的字符串,它来作为索引,或许称为键。赋值方式与索引数组也没有什么不一样。