可替换的参数:处理或/并扩展变量
${a}和$a是相同的,都是表示变量a的值。在一些环境中,使用${a}比较不会引起误解.
可以把变量和字符串连接.
1 your_id=${USER}-on-${HOSTNAME} |
如果变量没有被设置,使用默认值。
1 echo ${username-`whoami`} |
![]() |
${parameter-default}和${parameter:-default}几乎是相等的。它们之间的差别是:当一个参数已被声明,但是值是NULL的时候两者不同.
默认值结构可以在脚本中提供一个没有传递命令行参数时的默认值.
|
如果变量parameter没有设置,把它设置成默认值.
两种形式几乎相同,只是和上面的一样[1]:只有当$parameter变量被声明且被设置成null值时不同.
1 echo ${username=`whoami`} |
如果变量parameter设置,使用alt_value作为新值,否则使用空字符串。
除了引起的当变量被声明且值是空值时有些不同外,两种形式几乎相等。请看下面的例子.
1 echo "###### \${parameter+alt_value} ########" |
- ${parameter?err_msg}, ${parameter:?err_msg}
-
如果变量parameter已经设置,则使用该值,否则打印err_msg错误信息。
这两种形式几乎相同,仅有和上面所说的一点不同:带有:使当变量已声明但值是空值时不同.
例子 9-14. 使用参数替换和错误信息
1 #!/bin/bash |
例子 9-15. 变量替换和"usage"信息[译者注:通常就是帮助信息]
1 #!/bin/bash |
变量替换与/或扩展. 下面的各种表达式是expr字符串操作中match的补充(参考Example 12-9). 它们通常都用来解析文件路径名.
- ${#var}
-
字符串长度(即变量$var的字符个数)。对于数组来说,${#array}是数组的第一个元素的升序.
例外情况:
-
${#*}和${#@} 表示位置参数的个数.
-
对于一个数组来说,${#array[*]}和${#array[@]}表示数组中元素的个数.
例子 9-16. 变量值的长度
1 #!/bin/bash
2 # length.sh
3
4 E_NO_ARGS=65
5
6 if [ $# -eq 0 ] # 必须要有命令行参数给这个演示程序.
7 then
8 echo "Please invoke this script with one or more command-line arguments."
9 exit $E_NO_ARGS
10 fi
11
12 var01=abcdEFGH28ij
13 echo "var01 = ${var01}"
14 echo "Length of var01 = ${#var01}"
15 # 现在,让我们在变量值内嵌入一个空格.
16 var02="abcd EFGH28ij"
17 echo "var02 = ${var02}"
18 echo "Length of var02 = ${#var02}"
19
20 echo "Number of command-line arguments passed to script = ${#@}"
21 echo "Number of command-line arguments passed to script = ${#*}"
22
23 exit 0
-
- ${var#Pattern}, ${var##Pattern}
-
删除从$var前端开始的最短或最长匹配$Pattern的字符串。
例子 A-7中的用法示例:
1 # 摘自"days-between.sh"例子的函数
2 # 剥去传递来的参数的前引0.
3
4 strip_leading_zero () # 剥去传递的参数中可能存在的前导0
5 { #
6 return=${1#0} # "1"表示变量"$1" -- 传给函数的参数.
7 } # 而"0"表示要从"$1"前端剥掉的字符 -- 剥掉0Manfred Schwarb给出了比上面更多的细节的例子:
1 strip_leading_zero2 () # 剥除前导的0字符,因为不这样
2 { # Bash会把这串字符当成八进制值.
3 shopt -s extglob # 激活扩展匹配.
4 local val=${1##+(0)} # 使用局部变量,匹配最长的0.
5 shopt -u extglob # 禁用扩展匹配.
6 _strip_leading_zero2=${val:-0}
7 # 如果输入是0,返回0来替换返回"".
8 }另外一个usage(帮助信息)示例:
1 echo `basename $PWD` # 当前工作目录的基本名字.
2 echo "${PWD##*/}" # 当前工作目录的基本名字.
3 echo
4 echo `basename $0` # 脚本名.
5 echo $0 # 脚本名.
6 echo "${0##*/}" # 脚本名.
7 echo
8 filename=test.data
9 echo "${filename##*.}" # data
10 # 文件的扩展名. - ${var%Pattern}, ${var%%Pattern}
-
删除从$var前端开始的最短或最长匹配$Pattern的字符串。
例子 9-17. 在参数替换中的模式匹配
1 #!/bin/bash |
例子 9-18. 更改文件扩展名(后缀):
1 #!/bin/bash |
-
这些结构从ksh中学习而来.
- ${var:pos}
-
变量var被展开成从位移pos个字符往后的值.
- ${var:pos:len}
-
从变量var中展开成从位移pos的字符往后最长为len的字符串。参考例子 A-14中这个操作符的创造性用法。
- ${var/Pattern/Replacement}
-
在变量var第一个匹配Pattern的字符串用Replacement代替.
如果省略了Replacement ,则第一个匹配Pattern的字符串会被删除.
- ${var//Pattern/Replacement}
-
全局替换Global replacement.所有在变量var中被Pattern匹配到的都由Replacement代替.
和上面的一样,如果Replacement被省略,则所有的匹配Pattern的字符串都会被删除.
例子 9-19. 用模式匹配来解析任意的字符串
1 #!/bin/bash
2
3 var1=abcd-1234-defg
4 echo "var1 = $var1"
5
6 t=${var1#*-*}
7 echo "var1 (with everything, up to and including first - stripped out) = $t"
8 # t=${var1#*-} 也一样,
9 #+ 因为 # 匹配最短的字符串,
10 #+ 并且 * 匹配前面所说的所有字符,也包括空字符串.
11 # (多谢Stephane Chazelas指出这一点.)
12
13 t=${var1##*-*}
14 echo "If var1 contains a \"-\", returns empty string... var1 = $t"
15
16
17 t=${var1%*-*}
18 echo "var1 (with everything from the last - on stripped out) = $t"
19
20 echo
21
22 # -------------------------------------------
23 path_name=/home/bozo/ideas/thoughts.for.today
24 # -------------------------------------------
25 echo "path_name = $path_name"
26 t=${path_name##/*/}
27 echo "path_name, stripped of prefixes = $t"
28 # 在这个特例中,和 t=`basename $path_name` 效果一样.
29 # t=${path_name%/}; t=${t##*/} 是更一般的解决办法,
30 #+ 但有时还是会失败.
31 # 如果$path_name 以一个新行符结尾,那么 `basename $path_name` 就不能正常工作了,
32 #+ 但上面的表达式可以正常工作.
33 # (多谢, S.C.)
34
35 t=${path_name%/*.*}
36 # 效果和 t=`dirname $path_name` 一样
37 echo "path_name, stripped of suffixes = $t"
38 # 有时这会失败,比如"../", "/foo////", # "foo/", "/".
39 # 移除前缀,特别当basename没有前缀时,
40 #+ 但目录名可以,但也使问题也更复杂了.
41 # (多谢, S.C.)
42
43 echo
44
45 t=${path_name:11}
46 echo "$path_name, with first 11 chars stripped off = $t"
47 t=${path_name:11:5}
48 echo "$path_name, with first 11 chars stripped off, length 5 = $t"
49
50 echo
51
52 t=${path_name/bozo/clown}
53 echo "$path_name with \"bozo\" replaced by \"clown\" = $t"
54 t=${path_name/today/}
55 echo "$path_name with \"today\" deleted = $t"
56 t=${path_name//o/O}
57 echo "$path_name with all o's capitalized = $t"
58 t=${path_name//o/}
59 echo "$path_name with all o's deleted = $t"
60
61 exit 0
- ${var/#Pattern/Replacement}
-
如果变量var的前缀匹配模式Pattern,则用Replacement代替匹配模式的字符串.
- ${var/%Pattern/Replacement}
-
如果变量var的后缀匹配模式Pattern,则用Replacement代替匹配模式的字符串.
例子 9-20. 匹配字符串前缀和后缀的模式
1 #!/bin/bash
2 # var-match.sh:
3 # Demo of pattern replacement at prefix / suffix of string.
4
5 v0=abc1234zip1234abc # 初值.
6 echo "v0 = $v0" # abc1234zip1234abc
7 echo
8
9 # 匹配字符串的前缀(开头).
10 v1=${v0/#abc/ABCDEF} # abc1234zip1234abc
11 # |-|
12 echo "v1 = $v1" # ABCDEF1234zip1234abc
13 # |----|
14
15 # 匹配字符串的后缀(尾部).
16 v2=${v0/%abc/ABCDEF} # abc1234zip123abc
17 # |-|
18 echo "v2 = $v2" # abc1234zip1234ABCDEF
19 # |----|
20
21 echo
22
23 # ----------------------------------------------------
24 # 必须匹配字符串的开头/尾部,
25 #+ 否则不会发生替换.
26 # ----------------------------------------------------
27 v3=${v0/#123/000} # 匹配,但不是在开头.
28 echo "v3 = $v3" # abc1234zip1234abc
29 # 不会被替换.
30 v4=${v0/%123/000} # 匹配,但不是尾部.
31 echo "v4 = $v4" # abc1234zip1234abc
32 # 不会被替换.
33
34 exit 0
- ${!varprefix*}, ${!varprefix@}
-
匹配所有前面声明过的变量,并且变量名以varprefix开头.
1 xyz23=whatever
2 xyz24=
3
4 a=${!xyz*} # 展开为声明过的并以"xyz".
5 echo "a = $a" # a = xyz23 xyz24
6 a=${!xyz@} # Same as above.
7 echo "a = $a" # a = xyz23 xyz24
8
9 # Bash, 版本2.04,增加了这个属性.