变量
变量是什么
在Bash shell中,只有一种数据型态:以字符组成的字符串。Bash Shell把任何存储在变量中的值,皆视为以字符组成的“字符串”。
要使用Bash Shell变量,不需要经过实现声明。
每个Shell环境都会维护一份它们自己的变量空间,彼此不互相影响。
变量命名
变量名可用英文字母、数字及下划线组成,但开头第一个字符不能是数字;变量名长度不限制;大小写敏感;
变量赋值
给变量赋值时,等号两边不可以有空白;若变量值有空白,则要用引号括起来。
变量和引号
推荐习惯:把字符串用双引号或单引号括起来。
在双引号中,可进行以下3个操作:替换变量;替换命令执行结果;替换算术运算结果。
单引号的作用是形成一个所见即所得的字符串,不会进行任何变量替换的操作。
取变量值
$变量名
或 ${变量名}
前者在变量名后面是空白符时使用,后者在变量名与其他字母、数字、下划线混合时使用。
取消变量:
取消变量就是把变量从变量空间删除释放。
unset 变量名
unset -v 变量名
unset -f 函数名
清空变量
变量仍然存在,只不过值是长度为0的字符串。
变量名=
环境变量
父shell输出环境变量后,后续的各种操作包括子shell都可提取该变量的值。
export var="var value"
declare -x envVar="var value"
bash内置变量
CDPATH: cd命令的搜索路径,自定义CDPATH,可缩短键入路径文件名的长度。
IFS:定义字段分隔符。默认为:空格符、tab字符、换行符。
OLDPWD:前一个工作目录。
$0:执行程序的名称。
$1-$n:位置参数。传入程序或函数的参数,第一个是$1, n超过9的,用${n}
$*:代表所有位置参数,并且视为一个字符串。
$@:代表所有位置参数,但$@代表各位置参数的串行。
$#:位置参数的个数。
$-:bash shell目前使用的功能选项。
$?:上一个命令执行结束后的返回结果。通常0表示成功,非0失败。
$$:目前shell的进程编号。
$!:上一个后台程序的进程编号。
$_:用途有3种:
1. script执行时,bash的绝对路径;
2. 上一个命令执行时,最后一个位置参数;
3. 检查邮件时,值为邮件文件名。
调整变量属性
readonly用法
readonly 用于设置只读变量。
readonly 变量名
readonly -f 函数名
readonly -a 数组名
declare用法
选项 用途 范例
-p 显示变量属性 declare -p x
-a 变量是个数组 declare -a arr
-f 搜索命令时,只找函数 declare -f showit
-i 变量是整数 declare -i intvar
-F 显示所有函数名称及其属性 declare -F
-r 设定只读变量 declare -r a
-t 设置变量具有trace属性 declare -t xyz=11
-x 设为环境变量 declare -x PATH
举例
代码:
var="i am user defined variable ."
vartoo="$var too ."
echo "lets see their value, var:\"$var\", vartoo:\"${vartoo}\""
echo 'we cannot see their value, var:\"$var\", vartoo:\"${vartoo}\"'
unset vartoo
echo "after unset vartoo, lets see their value, var:\"$var\", vartoo:\"${vartoo}\""
declare -i int=123
echo "i am int type value is : $int"
int="given"
echo "after giving a string value, what is int value: $int"
结果:
lets see their value, var:"i am user defined variable .", vartoo:"i am user defined variable . too ."
we cannot see their value, var:\"$var\", vartoo:\"${vartoo}\"
after unset vartoo, lets see their value, var:"i am user defined variable .", vartoo:""
i am int type value is : 123
after giving a string value, what is int value: 0
数组
bash数组的元素个数没有限制,索引从0开始,不一定要连续。
建立数组:
一次设定每个元素值: B=(2 3 5 4)
,元素之间用空格分隔。
指定个别元素的索引: C=([3]=77 [1]=88 [5]=12)
。
指定某一元素索引,其余由系统接续: E=(124 [8]=188 266)
。
取值
${数组名[索引]}
: 取元素值。
${arr[@]}
:一次取出数组所有元素,以空白分隔每个元素;如果元素是字符串,且值含有空格,应该通过数组的索引列表进行遍历(应该总是通过索引列表进行遍历)。
${arr[*]}
:一次取出数组所有元素,连接成一个字符串。
取数组索引列表
${!数组变量[@]}
或 ${!数组变量[*]}
把数组变量的所有索引列出,各索引值之间用$IFS
定义的第一个分隔符隔开。
计算数组长度: ${#arr[@]} 或 ${#arr[*]}
计算数组某个元素的长度: ${#arr[索引]}
取消数组或数组元素
unset 数组名
unset 数组名[索引]
举例
代码:
arr=(3 2 404 0 5)
echo "arr length is ${#arr[@]}, ${#arr[*]}, length of element 2 is ${#arr[2]}"
unset arr[2]
echo "after unset arr[2], arr length is ${#arr[@]}, ${#arr[*]}, length of element 2 is ${#arr[2]}"
arr2=([3]="x y z" [1]=1 [5]=911)
echo -n "iterate arr2 element set: "
for i in ${arr2[@]}
do
echo -n $i ",,"
done
echo ""
echo -n "iterate arr2 by index set : "
for i in ${!arr2[@]}
do
printf "%s," "${arr2[$i]}"
done
echo ""
结果:
arr length is 5, 5, length of element 2 is 3
after unset arr[2], arr length is 4, 4, length of element 2 is 0
iterate arr2 element set: 1 ,,x ,,y ,,z ,,911 ,,
iterate arr2 by index set : 1,x y z,911,
here document
基本语法
命令 << 标记
........content ...
标记
这样会把命令和标记之间的内容,利用转向输入的方式交给该命令去处理。
标记可以是任何字符串,尽量选用不常用的字符组合,避免该字符串出现在输入的内容中造成bash误判。
bash支持变量替换,对标记加上单引号可关闭变量替换($var
),但命令扩展(反引号扩展)仍然是可以的。
bash中:
命令表示什么也不做,所以可以结合here document进行注释。
在标记前加上-
,表示抑制各行首TAB的作用。-
与<<
及标记之间不能有空格。
举例
: << coment_label
comment line 1
comment line 2
coment_label
sh <<-cmd_label
echo "call date command from here document :`date`"
echo "use var replace from here document :$var"
cmd_label
sh <<-'cmd_label'
echo "call date command from here document :`date`"
echo "use var replace from here document :$var"
cmd_label
变量扩展
条件式 目的 处理
${var:-默认值} 回传的结果一定要有值 如果var不存在或为空值,返回默认值,否则返回变量值。
${var:=默认值} 给空值变量设置一个默认值 如果var不存在或为空值,把var设为默认值。
${var:?错误信息} 检查条件是否完备 如果var不存在或为空值,显示'变量名称:提示信息,停止执行script。
${var:+默认值} 判断某事是否为真 Var存在且非空,返回默认值,否则返回变量值。
在上表各式中,若移除:
,则只测试存在性,不测空值。
记忆法:
: 空 测空值
- 负向 测不存在
= 设置 给空值变量设一个默认值
? 有问题 检查条件是否完备后再执行
+ 正向 测试存在
变量扩展
字符串的位置下标由0开始。
取部分位置参数
${@:起始位置}
${@:起始位置:个数}
取子串
${var:起始位置}
${var:起始位置:长度}
计算字符串长度
${#变量名}
或expr length "$变量名"
。
字符串截取
${变量#样式}
:从第一个字符开始匹配,删除最短匹配。
${变量##样式}
:从第一个字符开始匹配,删除最长匹配。
${变量%样式}
:从最后一个字符开始,删除最短匹配。
${变量%%样式}
: 从最后一个字符开始,删除最长匹配。
如果第一个字符或最后一个字符开始的字符串与样式不匹配,则不截取。
一种记忆方法:在键盘上#
在%
的左边,所以#
是从左开始,%
是从右开始;%
比%%
短,所以%
是最短匹配,%%
是最长匹配。
字符串替换
${var/pattern/replace_str}
:只替换第一个最长匹配。
${var//pattern/replace_str}
:替换所有的最长匹配。
${var/#pattern/replace_str}
:只从var开头匹配,用replace_str替换最长匹配。
${var/%pattern/replace_str}
:只从var结尾匹配,用replace_str替换最长匹配。
replace_str可以是变量,如:${var/pattern/var2}
上述替换串为空则表示删除匹配。
举例
代码:
str="hello world ."
echo "str=\"${str}\",length=${#str}" ',${str:4}=' "\"${str:4}\"" ',${str:4:4}=' "\"${str:4:5}\""
str2="xx x"
echo "\"${str/e*o/$str2}\", \"${str/e*o/------}\", \"${str/e*o/}\""
echo "${str/#h*o /abc}, ${str/%w*d ./$str2} "
echo '${str#e*o}=' "\"${str#e*o}\"" ',${str##e*o}=' "\"${str##e*o}\""
echo '${str#h*o}=' "\"${str#h*o}\"" ',${str##h*o}=' "\"${str##h*o}\""
echo '${str%w*o}=' "\"${str%w*o}\"" ',${str%%w*o}=' "\"${str%%w*o}\""
echo '${str%w*.}=' "\"${str%w*.}\"" ',${str%%w*.}=' "\"${str%%w*.}\""
结果:
str="hello world .",length=13 ,${str:4}= "o world ." ,${str:4:4}= "o wor"
"hxx xrld .", "h------rld .", "hrld ."
abcworld ., hello xx x
${str#e*o}= "hello world ." ,${str##e*o}= "hello world ."
${str#h*o}= " world ." ,${str##h*o}= "rld ."
${str%w*o}= "hello world ." ,${str%%w*o}= "hello world ."
${str%w*.}= "hello " ,${str%%w*.}= "hello "
取变量名称列表
${!开头字符串@}
或 ${!开头字符串*}
把所有以指定字符串开头的变量名列出,各变量之间用$IFS
定义的第一个分隔符隔开。
命令替换
命令替换是把命令执行后的标准输出放入变量中。
var=$(命令)
var=`命令`
在这个过程中,默认会自动删除命令结果里的换行符。
算术运算
名称 语法 范例
算术扩展 $((算术式)) r=$((2+5*8)) 如果表达式有变量,变量名前不要加$
使用外部程序expr expr 算术式 r=`expr 4+5`
使用$[] $[算术式] R=$[4+5]
使用内置命令declare declare -i var=算术式 declare -i r=8+6
使用内置命令let let 算术式 let r=5+6
在求值时,如果变量不存在或空值,则其值为0.
用expr
做算术运算时,如果表达式里含有shell的特殊字符,需要进行转义。expr在我的ubuntu12.04 vps上没效果。
使用declare
、let
的注意事项:
算式中,运算符和操作数之间不可以有空格,要紧密连接;
特殊符号不必使用\
转义;
算式中可包含其他变量,变量前不必加$
。
从各种限制来看,还是使用$((expression))
最好。
举例
代码:
declare -i int=123
declare -i int2=123*2
r=$(( int * 3 ))
r4=$[$int * 4]
r5=`expr 4*5`
let r6=$int*6
#r5=`expr $int*5`
echo '$int=' $int '$,int2=' $int2 ',$r=' $r
echo '$r4=' $r4 ',$r5=' $r5 ',$r6=' $r6
结果:
int= 123 $,int2= 246 ,$r= 369
$r4= 492 ,$r5= 4*5 ,$r6= 738
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。