1) 赋值“=”和扩充变量值
在设定变量的时侯,得遵照以下规则:
* 等号左右两边不能使用区隔符号(IFS),也应避免使用 shell 的保留字符(meta charactor)。
* 变量名称不能使用 $ 符号。
* 由字母和下划线组成,而且变量名称的第一个字母不能是数字(number)。
* 变量名称长度不可超过 256 个字母。
* 变量名称及变量值之大小写是敏感的(case sensitive)
例如:NAME=ice_walk 给变量NAME赋值为ice_walk
在应用变量NAME的时候,在NAME前加"$"便可。
例如:echo $NAME
扩充"(append)变量值:
除了shell中的meta,其它的[^a-zA-Z0-9_]几乎均可以做单词边界。这些功能有时候会在程序中有意想不到的做用。例如:
$ a=bcd
$ echo $a.php 得:bcd.php
$ echo $a%b 得:bcd%b
$ echo /$a/bc 得:/bcd/bc
对于shell中的meta字符,则使用backslash。
$ echo $a\*b 得:bcd*b
用户也能够在命令行上同时对多个变量赋值,赋值语句之间用空格分开:
X=x Y=y (注意变量赋值是从右到左进行的)
X=$Y Y=y X的值是y
X=z Y=$Z Y的值是空 (变量未赋值时,shell不报错,而是赋值为空)
内置命令eval:
在要求多于一次字符串求值的状况下可使用内置命令 eval。例如,若是变量 X 有值 $y, 而且若 y 有值 pqr 则:eval echo $X
将回显字符串 pqr。
通常的,eval 命令求值它的实际参数(与全部命令同样)并把这个结果做为给 shell 的输入来对待。读这个输入并执行做为结果的命令。例如:
wg=\'eval who|grep\'
$wg fred
等价于:who|grep fred
在这例子中,须要 eval 的缘由是替换以后不解释元字符如 |。
局部变量
在 BASH 程序中若是一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。BASH 中,在变量首次被赋初值时加上 local 关键字就能够声明一个局部变量。
C-shell的用户应该注意:
C-shell中的赋值不一样于Bourne和Korn shell。C-shell使用set命令进行赋值:
$set LOOK = /usr/mydir (注意在等号两边要加空格,好像不加也能够)
就象文件名的置换同样,变量名的置换也是在调用程序前进行。在变量替换中,变量的值取代了变量名。例如在:$ls $LOOK/filename 用 /usr/mydir/filename 作参数调用ls。
2) 变量替换${}
Shell 之因此强大,其中的一个因素是它能够在命令行中对变量做替换(substitution)处理。在命令行中使用者可使用 $ 符号加上变量名称(除了在用 = 号定义变量名称以外),将变量值给替换出来,而后再从新组建命令行。
通常状况下,$var 与 ${var} 并无啥不同。可是用 ${ } 会比较精确的界定变量名称的范围,比方说:
$ A=B
$ echo $AB
本来是打算先将 $A 的结果替换出来,而后再补一个 B 字母于其后,但在命令行上,真正的结果倒是只会提换变量名称为 AB 的值出来。若使用 ${ } 就没问题了。
A、掐头去尾
假设咱们定义了一个变量为:file=/dir1/dir2/dir3/my.file.txt
咱们可用 ${ } 分别替换得到不一样的值:
${file#*/} 从变量file的字符串左边开始删除字符,直到第一个“/”:dir1/dir2/dir3/my.file.txt
${file##*/} 从变量file的字符串左边开始删除字符,直到最后一个“/”:my.file.txt
${file#*.} 从变量file的字符串左边开始删除字符,直到第一个“.”:file.txt
${file##*.} 从变量file的字符串左边开始删除字符,直到最后一个“.”:txt
${file%/*} 从右部开始拿掉字符,直到遇到(从右部数起的)第一个“/” :/dir1/dir2/dir3
${file%%/*} 从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“/”:(空值)
${file%.*} 从右部开始拿掉字符,直到遇到(从右部数起的)第一个“.”:/dir1/dir2/dir3/my.file
${file%%.*} 从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“.”:/dir1/dir2/dir3/my
记忆的方法为:
# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边)
单一符号是最小匹配﹔两个符号是最大匹配。
同时要注意:在 # 和 % 后可使用任何shell中的模式匹配。并不是仅限于*、.、/。
B、字串提取
${file:0:5} 提取最左边的 5 个字节:/dir1
${file:3} 去掉前面3个字符
${file:5:5} 提取第 5 个字节右边的连续 5 个字节:/dir2
C、字符串替换
${file/dir/path} 将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path} 将所有 dir 提换为 path:/path1/path2/path3/my.file.txt
不可使用 regexp , 只能用shell中 * 、? 的文件扩展方式。
D、通吃变量名
${!prefix*} 表明全部以prefix开始的变量名,各变量名称之间以空格符分隔
$ ab=1 abc=2 abcd=3
$ echo ${!ab*} 输出:ab abc abcd
E、变量赋值(没设定、空值、非空值)
${#myvar} 计算出变量值的长度
${myvar=default} 若 $myvar 没设定,则输出并取值 default。(保留空值及非空值)
${myvar:=default} 若 $myvar 没设定或为空值,则输出并取值 default。(保留非空值)
${myvar+default} 若 $myvar 设定为空值或非空值,输出但不取值 default,不然返回空(null)。
${myvar:+default} 若 $myvar 设定为非空值,输出但不取值 default,不然返回空(null)。
${myvar-default} 若 $myvar 没设定,输出但不取值 default。(保留空值及非空值)
${myvar:-default} 若 $myvar 没设定或为空值,输出但不取值 default。(保留非空值)
${myvar?default} 若 $myvar 没设定,将 default 输出至 STDERR。(不取值,保留空值及非空值)
${myvar:?default} 若 $myvar 没设定或为空值,将 default 输出至STDERR。(不取值,保留非空值)
(此表请看下面的图)
变量替换的值也能够是` `括起来的命令:$USERDIR={$Mydir:-`pwd`}${var:?message} 当没有指定message时,shell将显示一条默认的消息,例如: $UNAME=$echo ${UNAME:?} 结果显示:sh:UNAME:parameter null or not set速记法:n = 慈善家(你没有才给你)n + 商人(你有才给换)n - 假慈善家(代表上才给)n ? 牛皮精(只说不作)n 加“:”后,至关于把“空值”也看成“unset”值处理,对有值的变量则无影响F、bash 的组数(array)处理通常而言,A="a b c def" 这样的变量只是将 $A 替换为一个单一的字符串,可是改成 A=(a b c def) ,则是将 $A 定义为组数。bash 的组数替换方法可参考以下方法:${A[@]} 或 ${A} 可获得 a b c def (所有组数);${A[0]} 可获得 a (第一个组数),${A[1]} 则为第二个组数;${#A[@]} 或 ${#A} 可获得 4 (所有组数数量);${#A[0]} 可获得 1 (即第一个组数(a)的长度),${A[3]} 可获得 3 (第一个组数(def)的长度);A[3]=xyz 则是将第 4 个组数从新定义为 xyz。3) 清除赋值:unset <变量>变量一旦通过 unset 取消以后,其结果是将整个变量拿掉,而不只是取消其变量值。以下两行实际上是很不同的:$ A=$ unset A第一行只是将变量 A 设定为"空值"(null value),但第二行则让变量 A 不在存在:$ A=$ echo $A 打印输出为空$ unset A$ echo $A 打印输出为空请务必能识别 null value 与 unset 的本质区别,这在一些进阶的变量处理上是很严格的。与export同样,unset 命令行也一样会做变量替换(这其实就是 shell 的功能之一),所以:A=BB=Cunset $A 事实上所取消的变量是 B 而不是 A 。4) $( )、` `、$(( ))、(( )) A、$( )与 ` `(反引号) 都是用来作命令替换用(command substitution)的。所谓的命令替换与前面的变量替换差很少,都是用来重组命令行:完成引号里的命令行,而后将其结果替换出来,再重组命令行。例如:$ echo last sunday is $(date -d "last sunday" +%Y-%m-%d) ,如此即可获得上一星期天的日期了。在操做上,用 $( ) 或 ` ` 都无所谓,只是我"我的"比较喜欢用 $( ) ,理由是:(1) ` ` 很容易与 ' ' ( 单引号)搞混乱。有时在一些奇怪的字形显示中,两种符号是如出一辙的(直竖两点)。(2) 在多层次的复合替换中,` ` 需要额外的跳脱( \` )处理,而 $( ) 则比较直观。例如:command1 `command2 `command3` `这是错的。本来的意图是要在 command2 `command3` 先将 command3 提换出来给command 2 处理,而后再将结果传给 command1 `command2 ...` 来处理。然而,真正的结果在命令行中倒是分红了 `command2 ` 与 `` 两段。正确的输入应该是:command1 `command2 \`command3\` `要否则,换成 $( ) 就没问题了:command1 $(command2 $(command3))不过,$( ) 并非没有弊端的, ` ` 基本上可用在所有的 unix shell 中使用,若写成 shell script ,其移植性比较高。而 $( ) 并不见的每一种 shell 都能使用,只能说,若你用 bash2 的话,确定没问题!例:经过$()实现对某目录下文件进行操做的功能:#!/bin/bashj=$(ls $1)for k in $jdo echo "$k" if [ $k = text ] then cat $k else echo no text fidoneB、$(( ))用来做整数运算在 bash 中,$(( )) 的整数运算符号大体有这些:+ - * / :分别为 "加、减、乘、除"。% :余数运算& | ^ !:分别为 "AND、OR、XOR、NOT" 运算。例:$ a=5; b=7; c=2$ echo $(( a+b*c )) #得19$ echo $(( (a+b)/c )) #得6$ echo $(( (a*b)%c)) #得1在 $(( )) 中的变量,可用 $ 符号来替换,也能够不用,如:$(( $a + $b * $c)) 也可获得 19 的结果。此外,$(( )) 还可做不一样进位(如二进制、八进位、十六进制)做运算呢,只是,输出结果皆为十进制而已:echo $((16#2a)) 结果为 42 (16进位转十进制)以一个实用的例子来看看吧:假如当前的 umask 是 022 ,那么新建文件的权限即为: $ umask 022$ echo "obase=8;$(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc644C、用 (( ))重定义变量值或做testinga=5; ((a++)) 可将 $a 重定义为 6a=5; ((a--)) 则为 a=4a=5; b=7; ((a < b)) 会获得 0 (true) 的返回值。常见的用于 (( )) 的测试符号有以下这些:<:小于>:大于<=:小于或等于>=:大于或等于==:等于!=:不等于不过,使用 (( )) 做整数测试时,请不要跟 [ ] 的整数测试搞混乱了。