Shell参数替换
时间:2008-11-07 来源:共舞秋雨
|
|
---|---|
参数替换 |
|
处理和(或)扩展变量 ${parameter}
与$parameter相同, 也就是变量parameter的值. 在某些上下文中, ${parameter}很少会产生混淆.
可以把变量和字符串组合起来使用.
1 your_id=${USER}-on-${HOSTNAME} |
1 echo ${username-`whoami`} |
${parameter-default} 和${parameter:-default}在绝大多数的情况下都是相同的. 只有在parameter已经被声明, 但是被赋null值得时候, 这个额外的:才会产生不同的结果. |
1 #!/bin/bash |
如果脚本并没有接收到来自命令行的参数, 那么默认参数结构将会提供一个默认值给脚本.
1 DEFAULT_FILENAME=generic.data |
${parameter=default}, ${parameter:=default} ${parameter=default} -- 如果变量parameter没声明, 那么就把它的值设为default. ${parameter:=default} -- 如果变量parameter没设置, 那么就把它的值设为default.
这两种形式基本上是一样的. 只有在变量$parameter被声明并且被设置为null值的时候, :才会引起这两种形式的不同. [1] 如上边所示.
1 echo ${username=`whoami`} |
${parameter+alt_value} -- 如果变量parameter被声明了, 那么就使用alt_value, 否则就使用null字符串.
${parameter:+alt_value} -- 如果变量parameter被设置了, 那么就使用alt_value, 否则就使用null字符串.
这两种形式绝大多数情况下都一样. 只有在parameter被声明并且设置为null值的时候, 多出来的这个:才会引起这两种形式的不同, 具体请看下边的例子.
1 echo "###### \${parameter+alt_value} ########" |
这两种形式绝大多数情况都是一样的. 和上边所讲的情况一样, 只有在parameter被声明并设置为null值的时候, 多出来的:才会引起这两种形式的不同.
例子 9-15. 使用参数替换和错误消息
1 #!/bin/bash 2 3 # 检查一些系统环境变量. 4 # 这是一种可以做一些预防性保护措施的好习惯. 5 # 比如, 如果$USER(用户在控制台上中的名字)没有被设置的话, 6 #+ 那么系统就会不认你. 7 8 : ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?} 9 echo 10 echo "Name of the machine is $HOSTNAME." 11 echo "You are $USER." 12 echo "Your home directory is $HOME." 13 echo "Your mail INBOX is located in $MAIL." 14 echo 15 echo "If you are reading this message," 16 echo "critical environmental variables have been set." 17 echo 18 echo 19 20 # ------------------------------------------------------ 21 22 # ${variablename?}结构 23 #+ 也能够检查脚本中变量的设置情况. 24 25 ThisVariable=Value-of-ThisVariable 26 # 注意, 顺便提一下, 27 #+ 这个字符串变量可能会被设置一些非法字符. 28 : ${ThisVariable?} 29 echo "Value of ThisVariable is $ThisVariable". 30 echo 31 echo 32 33 34 : ${ZZXy23AB?"ZZXy23AB has not been set."} 35 # 如果变量ZZXy23AB没有被设置的话, 36 #+ 那么这个脚本会打印一个错误信息, 然后结束. 37 38 # 你可以自己指定错误消息. 39 # : ${variablename?"ERROR MESSAGE"} 40 41 42 # 等价于: dummy_variable=${ZZXy23AB?} 43 # dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."} 44 # 45 # echo ${ZZXy23AB?} >/dev/null 46 47 # 使用命令"set -u"来比较这些检查变量是否被设置的方法. 48 # 49 50 51 52 echo "You will not see this message, because script already terminated." 53 54 HERE=0 55 exit $HERE # 不会在这里退出. 56 57 # 事实上, 这个脚本将会以返回值1作为退出状态(echo $?). |
例子 9-16. 参数替换和"usage"消息(译者注: 通常就是帮助信息)
1 #!/bin/bash |
参数替换与(或)扩展. 下边这些表达式都是对如何在expr字符串操作中进行match的补充. 这些特定的使用方法一般都用来解析文件所在的目录名.
变量长度/子串删除 ${#var}字符串长度(变量$var得字符个数). 对于array来说, ${#array}表示的是数组中第一个元素的长度.
例外情况:
|
1 #!/bin/bash |
从变量$var的开头删除最短或最长匹配$Pattern的子串. (译者注: 这是一个很常见的用法, 请读者牢记, 一个"#"表示匹配最短, "##"表示匹配最长.)
一个用法示例:
1 # 摘自例子"days-between.sh"的一个函数. |
下边给出的一个更加详细的例子:
1 strip_leading_zero2 () # 去掉开头可能存在的0(也可能有多个0), 因为如果不取掉的话, |
另一个用法示例:
1 echo `basename $PWD` # 当前工作目录的basename(就是去掉目录名). |
从变量$var的结尾删除最短或最长匹配$Pattern的子串. (译者注: 这是一个很常见的用法, 请读者牢记, 一个"%"表示匹配最短, "%%"表示匹配最长.)
Bash的版本2添加了一些额外选项. 例子 9-18. 参数替换中的模式匹配
1 #!/bin/bash 2 # patt-matching.sh 3 4 # 使用# ## % %%来进行参数替换操作的模式匹配. parameter substitution operators. 5 6 var1=abcd12345abc6789 7 pattern1=a*c # *(通配符)匹配a - c之间的任意字符. 8 9 echo 10 echo "var1 = $var1" # abcd12345abc6789 11 echo "var1 = ${var1}" # abcd12345abc6789 12 # (另一种形式) 13 echo "Number of characters in ${var1} = ${#var1}" 14 echo 15 16 echo "pattern1 = $pattern1" # a*c (匹配'a'到'c'之间的任意字符) 17 echo "--------------" 18 echo '${var1#$pattern1} =' "${var1#$pattern1}" # d12345abc6789 19 # 最短的可能匹配, 去掉abcd12345abc6789的前3个字符. 20 # |-| ^^^^^ 21 echo '${var1##$pattern1} =' "${var1##$pattern1}" # 6789 22 # 最长的可能匹配, 去掉abcd12345abc6789的前12个字符 23 # |----------| ^^^^^^ 24 25 echo; echo; echo 26 27 pattern2=b*9 # 匹配'b'到'9'之间的任意字符 28 echo "var1 = $var1" # 还是abcd12345abc6789 29 echo 30 echo "pattern2 = $pattern2" 31 echo "--------------" 32 echo '${var1%pattern2} =' "${var1%$pattern2}" # abcd12345a 33 # 最短的可能匹配, 去掉abcd12345abc6789的最后6个字符 34 # |----| ^^^^^^^ 35 echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a 36 # 最长的可能匹配, 去掉abcd12345abc6789的最后12个字符 37 # |-------------| ^^^^^^^^ 38 39 # 牢记, #和##是从字符串左边开始, 并且去掉左边的字符串, 40 # %和%%从字符串的右边开始, 并且去掉右边的字符串. 41 # (译者注: 有个好记的方法, 那就是察看键盘顺序, 记住#在%的左边. ^_^) 42 echo 43 44 exit 0 |
例子 9-19. 修改文件扩展名:
1 #!/bin/bash 2 # rfe.sh: 修改文件扩展名. 3 # 4 # 用法: rfe old_extension new_extension 5 # 6 # 示例: 7 # 将指定目录中所有的*.gif文件都重命名为*.jpg, 8 # 用法: rfe gif jpg 9 10 11 E_BADARGS=65 12 13 case $# in 14 0|1) # 竖线"|"在这里表示"或"操作. 15 echo "Usage: `basename $0` old_file_suffix new_file_suffix" 16 exit $E_BADARGS # 如果只有0个或1个参数的话, 那么就退出脚本. 17 ;; 18 esac 19 20 21 for filename in *.$1 22 # 以第一个参数为扩展名的全部文件的列表. 23 do 24 mv $filename ${filename%$1}$2 25 # 把筛选出来的文件的扩展名去掉, 因为筛选出来的文件的扩展名都是第一个参数, 26 #+ 然后把第2个参数作为扩展名, 附加到这些文件的后边. 27 done 28 29 exit 0 |
变量扩展/子串替换
这些结构都是从ksh中引入的. ${var:pos}
变量var从位置pos开始扩展(译者注: 也就是pos之前的字符都丢弃).
${var:pos:len}变量var从位置pos开始, 并扩展len个字符.
${var/Pattern/Replacement}使用Replacement来替换变量var中第一个匹配Pattern的字符串.
如果省略Replacement, 那么第一个匹配Pattern的字符串将被替换为空, 也就是被删除了.
${var//Pattern/Replacement}全局替换. 所有在变量var匹配Pattern的字符串, 都会被替换为Replacement.
和上边一样, 如果省略Replacement, 那么所有匹配Pattern的字符串, 都将被替换为空, 也就是被删除掉.
例子 9-20. 使用模式匹配来解析任意字符串
1 #!/bin/bash |
如果变量var的前缀匹配Pattern, 那么就使用Replacement来替换匹配到Pattern的字符串.
${var/%Pattern/Replacement}如果变量var的后缀匹配Pattern, 那么就使用Replacement来替换匹配到Pattern的字符串.
例子 9-21. 对字符串的前缀和后缀使用匹配模式
1 #!/bin/bash |
匹配所有之前声明过的, 并且以varprefix开头的变量.
1 xyz23=whatever |
注意事项
[1] |
如果在一个非交互脚本中, $parameter被设置为null的话, 那么这个脚本将会返回127作为退出状态码(127返回码对应的Bash错误码为命令未发现"command not found"). |
注:本文出自<<高级Bash脚本编程指南>>